@relyio/cli 0.11.0 → 0.12.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.
package/dist/index.js CHANGED
@@ -6,21 +6,19 @@ import path5 from 'path';
6
6
  import * as os from 'os';
7
7
  import os__default from 'os';
8
8
  import * as yaml from 'yaml';
9
- import { Scalar } from 'yaml';
10
9
  import { setTimeout as setTimeout$1 } from 'timers/promises';
11
10
  import { z } from 'zod';
12
- import objectHash from 'object-hash';
11
+ import objectHash22 from 'object-hash';
13
12
  import 'semver';
14
- import * as yaml2 from 'js-yaml';
15
- import * as fs4 from 'fs/promises';
16
- import { rm, readFile, writeFile, stat, mkdir } from 'fs/promises';
17
13
  import { glob } from 'glob';
18
14
  import { createJiti } from 'jiti';
19
15
  import { fileURLToPath } from 'url';
20
16
  import { execFileSync, spawn, execSync } from 'child_process';
21
- import chalk10 from 'chalk';
17
+ import chalk12 from 'chalk';
22
18
  import { format } from 'prettier';
23
19
  import { structuredPatch, diffWordsWithSpace } from 'diff';
20
+ import * as fs3 from 'fs/promises';
21
+ import { rm, readFile, writeFile, stat, mkdir } from 'fs/promises';
24
22
  import stripAnsi2 from 'strip-ansi';
25
23
  import { randomBytes, randomUUID, createHash } from 'crypto';
26
24
  import React3, { createContext, memo, useState, useEffect, useReducer, useMemo, useCallback, useContext, useRef, useSyncExternalStore } from 'react';
@@ -40,6 +38,7 @@ import inquirer2 from 'inquirer';
40
38
  import { Listr } from 'listr2';
41
39
  import { watch } from 'chokidar';
42
40
  import { EventEmitter } from 'events';
41
+ import * as yaml2 from 'js-yaml';
43
42
 
44
43
  var __defProp = Object.defineProperty;
45
44
  var __getOwnPropNames = Object.getOwnPropertyNames;
@@ -871,7 +870,7 @@ var init_chunk_BBUB7C2Z = __esm({
871
870
  }
872
871
  });
873
872
 
874
- // ../sdk/dist/chunk-CQHEG7QA.js
873
+ // ../sdk/dist/chunk-OVMIHAYK.js
875
874
  function defineRoute(route) {
876
875
  if (route.kind === "raw" && route.standardShape === void 0) {
877
876
  throw new Error("kind 'raw' requires a named StandardShape");
@@ -1078,8 +1077,8 @@ function hasValue(value) {
1078
1077
  return value !== void 0 && value !== "";
1079
1078
  }
1080
1079
  var HEADER_RETRY_AFTER, HEADER_IF_MATCH, HEADER_IDEMPOTENCY_KEY, FRESH_PARAMETER, K, rotr, PREVIEW_DATASET_PREFIX, READABLE_MAX, HASH_DIGITS, VISITOR_LIVE_PATH, VISITOR_QUERY, VISITOR_CURSOR, VISITOR_POLL_INTERVAL_MS, VISITOR_KEEPALIVE, VISITOR_FRAMES, VISITOR_CLOSE_CODES, VISITOR_CLOSE_RETRY, VISITOR_POLL_RETRY, VISITOR_ADMISSION_RETRY_AFTER_SECONDS, CHANGE_KINDS, RESYNC_REASONS, UNKNOWN_PREVIEW_RECHECK_MS, NOT_PREVIEW;
1081
- var init_chunk_CQHEG7QA = __esm({
1082
- "../sdk/dist/chunk-CQHEG7QA.js"() {
1080
+ var init_chunk_OVMIHAYK = __esm({
1081
+ "../sdk/dist/chunk-OVMIHAYK.js"() {
1083
1082
  init_chunk_XQ4QHWZE();
1084
1083
  __name(defineRoute, "defineRoute");
1085
1084
  __name(refuseMismatchedAlternate, "refuseMismatchedAlternate");
@@ -1452,7 +1451,7 @@ var init_chunk_H6IBQSMM = __esm({
1452
1451
  }
1453
1452
  });
1454
1453
 
1455
- // ../sdk/dist/chunk-NIUOPIIB.js
1454
+ // ../sdk/dist/chunk-VS2DEUTN.js
1456
1455
  function isResourceNotFound(error2) {
1457
1456
  return error2 instanceof ResourceNotFoundError;
1458
1457
  }
@@ -2697,15 +2696,15 @@ function resolveFromEnv(proc, now) {
2697
2696
  }
2698
2697
  function resolveFromFile(proc, now) {
2699
2698
  if (proc == null || typeof proc.cwd !== "function") return { state: "absent" };
2700
- const fs15 = getBuiltin(proc, "node:fs");
2699
+ const fs14 = getBuiltin(proc, "node:fs");
2701
2700
  const path27 = getBuiltin(proc, "node:path");
2702
- if (fs15 == null || path27 == null) return { state: "absent" };
2701
+ if (fs14 == null || path27 == null) return { state: "absent" };
2703
2702
  let dir = proc.cwd();
2704
2703
  for (; ; ) {
2705
2704
  const candidate = path27.join(dir, DEV_CONTEXT_DIR, DEV_CONTEXT_FILENAME);
2706
2705
  let raw = null;
2707
2706
  try {
2708
- if (fs15.existsSync(candidate)) raw = fs15.readFileSync(candidate, "utf8");
2707
+ if (fs14.existsSync(candidate)) raw = fs14.readFileSync(candidate, "utf8");
2709
2708
  } catch {
2710
2709
  return { state: "absent" };
2711
2710
  }
@@ -2871,10 +2870,10 @@ function randomClientId() {
2871
2870
  return Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
2872
2871
  }
2873
2872
  var PUBLISHABLE_KEY_PREFIX, isPublishableKey, PREVIEW_KEY_PREFIX, isPreviewKey, _SDKError, SDKError, _ResourceNotFoundError, ResourceNotFoundError, _ResourceConflictError, ResourceConflictError, _ResourceExpiredError, ResourceExpiredError, _MissingApiKeyError, MissingApiKeyError, _ReadOnlyKeyError, ReadOnlyKeyError, _PlanFeatureUnavailableError, PlanFeatureUnavailableError, _UsageQuotaExceededError, UsageQuotaExceededError, _RateLimitError, RateLimitError, _MethodNotAllowedError, MethodNotAllowedError, _PayloadTooLargeError, PayloadTooLargeError, _TransactionRolledBackError, TransactionRolledBackError, _ServiceIndeterminateError, ServiceIndeterminateError, _ServerError, ServerError, _UnknownContractError, UnknownContractError, _AuthorizationError, AuthorizationError, _InvalidApiKeyError, InvalidApiKeyError, _NetworkError, NetworkError, _TimeoutError, TimeoutError, _ConnectionError, ConnectionError, _BaseValidationError, BaseValidationError, _ValidationError, ValidationError, _InvalidPayloadError, InvalidPayloadError, _a, ContractBodyError, STALE_VERSION_GUIDANCE, _ErrorMapper, ErrorMapper, DECLARED_PATHS, COMPILED_ROUTES, IDEMPOTENT_METHODS, UNREACHABLE_CODES, _DefaultRetryPolicy, DefaultRetryPolicy, derived, unknown, announced, MAX_TIMER_DELAY_MS, _HttpClient, HttpClient, _ControlledHttpClient, ControlledHttpClient, API_KEY_HEADER, DATASET_HEADER, BROWSER_CONTROLLED_HEADERS, _EntryHandle, EntryHandle, _ContentClient, ContentClient, _FileUploadError, FileUploadError, _FileValidationError, FileValidationError, FILE_ERROR_CODES, _AssetFileBuilder, AssetFileBuilder, _AssetUploadBuilder, AssetUploadBuilder, _AssetClient, AssetClient, _DocumentHandle, DocumentHandle, _SingletonClient, SingletonClient, _SettingsClient, SettingsClient, CHANGES_POLL_TIMEOUT_MS, EXPIRED_REASONS2, _ChangesExpiredError, ChangesExpiredError, _LiveEdgeError, LiveEdgeError, LIVE_EDGE_OF_API, HTTP_SCHEME_OF, LIVE_KEEPALIVE_INTERVAL_MS, LIVE_SOCKET_OPEN_TIMEOUT_MS, LIVE_POLLS_BEFORE_SOCKET, SOCKET_CONNECTING, SOCKET_OPEN, AFTER_A_CLOSE, CLOSE_MEANING, NEEDS_PUBLISHABLE_KEY, VERBS, DEFAULT_CONFIG, devOverrideNotified, previewNotified, _TypedRelyIOClient, TypedRelyIOClient;
2874
- var init_chunk_NIUOPIIB = __esm({
2875
- "../sdk/dist/chunk-NIUOPIIB.js"() {
2873
+ var init_chunk_VS2DEUTN = __esm({
2874
+ "../sdk/dist/chunk-VS2DEUTN.js"() {
2876
2875
  init_chunk_BBUB7C2Z();
2877
- init_chunk_CQHEG7QA();
2876
+ init_chunk_OVMIHAYK();
2878
2877
  init_chunk_H6IBQSMM();
2879
2878
  init_chunk_XQ4QHWZE();
2880
2879
  PUBLISHABLE_KEY_PREFIX = "rly_pub_";
@@ -4134,7 +4133,10 @@ var init_chunk_NIUOPIIB = __esm({
4134
4133
  EntryHandle = _EntryHandle;
4135
4134
  _ContentClient = class _ContentClient2 extends EntryHandle {
4136
4135
  /**
4137
- * Create a new content entry.
4136
+ * Create a new content entry, published. The answer's `_metadata.warnings` lists each reference
4137
+ * the content type declares `weak` that the create made live while the entry it points at is
4138
+ * unpublished (`REFERENCE_NOT_PUBLISHED`) — `[]` when there are none; the create is never refused
4139
+ * for them.
4138
4140
  *
4139
4141
  * `locale` defaults to the client's own, and `dataset` to the client's (`client.with({ dataset })`
4140
4142
  * sets it for every call).
@@ -4954,7 +4956,10 @@ var init_chunk_NIUOPIIB = __esm({
4954
4956
  throw error2;
4955
4957
  }
4956
4958
  }
4957
- /** The API publishes on PATCH: there is no separate publish route. */
4959
+ /**
4960
+ * The API publishes on PATCH: there is no separate publish route. The answer's `_metadata` also
4961
+ * lists the links the write left pointing nowhere and its `warnings` (REL-3097).
4962
+ */
4958
4963
  patch(write, options) {
4959
4964
  return this.httpClient.fetchPayload(
4960
4965
  "/v1/singletons/{key}",
@@ -5012,15 +5017,11 @@ var init_chunk_NIUOPIIB = __esm({
5012
5017
  async reset(...args) {
5013
5018
  const [first, second] = args;
5014
5019
  const write = first !== void 0 && isRead(first) ? { ...versionCheckOf(first), options: second } : { locale: this.localeOf(first?.locale), ifMatch: void 0, options: first };
5015
- return this.httpClient.fetchPayload(
5016
- "/v1/settings/{groupId}/reset",
5017
- "post",
5018
- {
5019
- path: { groupId: this.name },
5020
- query: write.locale === void 0 ? void 0 : { locale: write.locale },
5021
- headers: DocumentHandle.headersOf(write, write.options)
5022
- }
5023
- );
5020
+ return this.httpClient.fetchPayload("/v1/settings/{groupId}/reset", "post", {
5021
+ path: { groupId: this.name },
5022
+ query: write.locale === void 0 ? void 0 : { locale: write.locale },
5023
+ headers: DocumentHandle.headersOf(write, write.options)
5024
+ });
5024
5025
  }
5025
5026
  /** The group's default values, as the schema declares them. */
5026
5027
  async getDefaults() {
@@ -5973,9 +5974,9 @@ function snapToLadder(value) {
5973
5974
  var FOLLOW_RETRY_BASE_MS, FOLLOW_RETRY_MAX_MS, FOLLOW_BACK_OFF_MAX_MS, LOCALE_STATUS_PUBLISHED, IMAGE_LADDER;
5974
5975
  var init_dist2 = __esm({
5975
5976
  "../sdk/dist/index.js"() {
5976
- init_chunk_NIUOPIIB();
5977
- init_chunk_NIUOPIIB();
5978
- init_chunk_CQHEG7QA();
5977
+ init_chunk_VS2DEUTN();
5978
+ init_chunk_VS2DEUTN();
5979
+ init_chunk_OVMIHAYK();
5979
5980
  init_chunk_XQ4QHWZE();
5980
5981
  FOLLOW_RETRY_BASE_MS = 1e3;
5981
5982
  FOLLOW_RETRY_MAX_MS = 3e4;
@@ -6636,72 +6637,6 @@ var init_exit_codes = __esm({
6636
6637
  }
6637
6638
  });
6638
6639
 
6639
- // ../../domain/schema/dist/chunk-IJSOONHT.js
6640
- function isLeapYear(year) {
6641
- return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
6642
- }
6643
- function isCalendarDay(year, month, day) {
6644
- if (month < 1 || month > 12 || day < 1) return false;
6645
- const last = month === 2 && isLeapYear(year) ? 29 : DAYS_IN_MONTH[month - 1];
6646
- return day <= last;
6647
- }
6648
- function utcMilliseconds(year, month, day, hour, minute, second, millisecond) {
6649
- const date = /* @__PURE__ */ new Date(0);
6650
- date.setUTCFullYear(year, month - 1, day);
6651
- date.setUTCHours(hour, minute, second, millisecond);
6652
- return date.getTime();
6653
- }
6654
- function offsetMinutes(offset) {
6655
- if (offset === "Z" || offset === "z") return 0;
6656
- const sign = offset.startsWith("-") ? -1 : 1;
6657
- const digits = offset.slice(1).replace(":", "");
6658
- const hours = Number(digits.slice(0, 2));
6659
- const minutes = digits.length > 2 ? Number(digits.slice(2, 4)) : 0;
6660
- if (hours > 23 || minutes > 59) return void 0;
6661
- return sign * (hours * 60 + minutes);
6662
- }
6663
- function utcText(ms) {
6664
- const date = new Date(ms);
6665
- const year = date.getUTCFullYear();
6666
- if (Number.isNaN(ms) || year < 0 || year > 9999) return void 0;
6667
- return date.toISOString();
6668
- }
6669
- function instantOf(ms) {
6670
- const instant = utcText(ms);
6671
- return instant === void 0 ? void 0 : { kind: "instant", instant, day: instant.slice(0, 10), ms };
6672
- }
6673
- function readInstantText(text, grammar) {
6674
- const match = grammar.exec(text);
6675
- if (match === null) return void 0;
6676
- const [, y, mo, d, h, mi, s, fraction, offset] = match;
6677
- const year = Number(y);
6678
- const month = Number(mo);
6679
- const day = Number(d);
6680
- const hour = Number(h);
6681
- const minute = Number(mi);
6682
- const second = s === void 0 ? 0 : Number(s);
6683
- if (!isCalendarDay(year, month, day)) return void 0;
6684
- const leap = hour === 23 && minute === 59 && second === 60;
6685
- if (hour > 23 || minute > 59 || second > 59 && !leap) return void 0;
6686
- const east = offsetMinutes(offset);
6687
- if (east === void 0) return void 0;
6688
- const millisecond = fraction === void 0 ? 0 : Number(fraction.slice(1, 4).padEnd(3, "0"));
6689
- const wall = utcMilliseconds(year, month, day, hour, minute, leap ? 59 : second, millisecond);
6690
- return instantOf(wall - east * 6e4 + (leap ? 1e3 - millisecond : 0));
6691
- }
6692
- function normalizeInstant(value) {
6693
- if (typeof value !== "string") return void 0;
6694
- const read = readInstantText(value, STORED_INSTANT);
6695
- return read?.kind === "instant" ? read.instant : void 0;
6696
- }
6697
- var STORED_INSTANT, DAYS_IN_MONTH;
6698
- var init_chunk_IJSOONHT = __esm({
6699
- "../../domain/schema/dist/chunk-IJSOONHT.js"() {
6700
- STORED_INSTANT = /^(\d{4})-(\d{2})-(\d{2})[Tt ](\d{2}):(\d{2}):(\d{2})(\.\d+)?([Zz]|[+-]\d{2}(?::?\d{2})?)$/;
6701
- DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
6702
- }
6703
- });
6704
-
6705
6640
  // ../../../node_modules/.pnpm/re2js@2.8.6/node_modules/re2js/build/index.js
6706
6641
  var RE2Flags, PublicFlags, ASCII_SIZE, ASCII_TO_UPPER, ASCII_TO_LOWER, MAX_BMP, Codepoint, UnicodeRangeTable, B64_MAP, decodeVLQ, decodeRanges, decodeOrbit, LazyMap, UnicodeTables, Unicode, FAST_PATH_TABLE_SIZE, WORD_RUNE_TABLE, cachedNativeEncoder, cachedNativeDecoder, Utils, createEnum, MatcherInputBase, Utf8MatcherInput, Utf16MatcherInput, MatcherInput, MachineInputBase, MachineUTF8Input, MachineUTF16Input, MachineInput, RE2JSException, RE2JSSyntaxException, RE2JSCompileException, RE2JSGroupException, RE2JSFlagsException, RE2JSInternalException, Matcher, Inst, Queue, Machine, hashPCs, arraysEqual, DFAState, DFA, VISITED_BITS, MAX_BACKTRACK_PROG, INITIAL_JOB_CAPACITY, MAX_BACKTRACK_VECTOR, BitState, bitStatePool, Backtracker, QueueOnePass, mergeRuneSets, OnePassProg, onePassCopy, makeOnePass, cleanupOnePass, OnePass, Regexp, AhoCorasick, Prefilter, PrefilterTree, PatchList, Prog, Frag, Compiler, Simplify, CharGroup, code1, code2, code3, PERL_GROUPS, code4, code5, code6, code7, code8, code9, code10, code11, code12, code13, code14, code15, code16, code17, POSIX_GROUPS, CharClass, StringIterator, Parser, RE2, TranslateRegExpString, RE2JS;
6707
6642
  var init_build = __esm({
@@ -13804,22 +13739,22 @@ function join(at, member) {
13804
13739
  }
13805
13740
  function keyCountsOf(nodes) {
13806
13741
  const counts = /* @__PURE__ */ new Map();
13807
- const visit22 = (held) => {
13742
+ const visit2 = (held) => {
13808
13743
  if (!Array.isArray(held)) return;
13809
13744
  for (const node of held) {
13810
13745
  if (!isRecord3(node)) continue;
13811
13746
  if (typeof node._key === "string" && node._key !== "") {
13812
13747
  counts.set(node._key, (counts.get(node._key) ?? 0) + 1);
13813
13748
  }
13814
- visit22(node.children);
13749
+ visit2(node.children);
13815
13750
  if (isRichTextShapeType(node._type)) {
13816
13751
  for (const member of Object.values(node)) {
13817
- if (isNestedTree(member)) visit22(member.children);
13752
+ if (isNestedTree(member)) visit2(member.children);
13818
13753
  }
13819
13754
  }
13820
13755
  }
13821
13756
  };
13822
- visit22(nodes);
13757
+ visit2(nodes);
13823
13758
  return counts;
13824
13759
  }
13825
13760
  function nodeAt(at, nodes, index, held) {
@@ -14309,8 +14244,8 @@ function narrowingProblemsIn(nodes, at, place, narrowing, problems, held) {
14309
14244
  }
14310
14245
  }
14311
14246
  }
14312
- function marksOfRun(run3) {
14313
- return run3.marks ?? [];
14247
+ function marksOfRun(run4) {
14248
+ return run4.marks ?? [];
14314
14249
  }
14315
14250
  function listOf(allowed) {
14316
14251
  return allowed.size === 0 ? "none" : [...allowed].join(", ");
@@ -14444,6 +14379,72 @@ var init_chunk_J57LV7E6 = __esm({
14444
14379
  SHAPE_PLACE_NAMES = { block: "a block", inline: "an inline element" };
14445
14380
  }
14446
14381
  });
14382
+
14383
+ // ../../domain/schema/dist/chunk-IJSOONHT.js
14384
+ function isLeapYear(year) {
14385
+ return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
14386
+ }
14387
+ function isCalendarDay(year, month, day) {
14388
+ if (month < 1 || month > 12 || day < 1) return false;
14389
+ const last = month === 2 && isLeapYear(year) ? 29 : DAYS_IN_MONTH[month - 1];
14390
+ return day <= last;
14391
+ }
14392
+ function utcMilliseconds(year, month, day, hour, minute, second, millisecond) {
14393
+ const date = /* @__PURE__ */ new Date(0);
14394
+ date.setUTCFullYear(year, month - 1, day);
14395
+ date.setUTCHours(hour, minute, second, millisecond);
14396
+ return date.getTime();
14397
+ }
14398
+ function offsetMinutes(offset) {
14399
+ if (offset === "Z" || offset === "z") return 0;
14400
+ const sign = offset.startsWith("-") ? -1 : 1;
14401
+ const digits = offset.slice(1).replace(":", "");
14402
+ const hours = Number(digits.slice(0, 2));
14403
+ const minutes = digits.length > 2 ? Number(digits.slice(2, 4)) : 0;
14404
+ if (hours > 23 || minutes > 59) return void 0;
14405
+ return sign * (hours * 60 + minutes);
14406
+ }
14407
+ function utcText(ms) {
14408
+ const date = new Date(ms);
14409
+ const year = date.getUTCFullYear();
14410
+ if (Number.isNaN(ms) || year < 0 || year > 9999) return void 0;
14411
+ return date.toISOString();
14412
+ }
14413
+ function instantOf(ms) {
14414
+ const instant = utcText(ms);
14415
+ return instant === void 0 ? void 0 : { kind: "instant", instant, day: instant.slice(0, 10), ms };
14416
+ }
14417
+ function readInstantText(text, grammar) {
14418
+ const match = grammar.exec(text);
14419
+ if (match === null) return void 0;
14420
+ const [, y, mo, d, h, mi, s, fraction, offset] = match;
14421
+ const year = Number(y);
14422
+ const month = Number(mo);
14423
+ const day = Number(d);
14424
+ const hour = Number(h);
14425
+ const minute = Number(mi);
14426
+ const second = s === void 0 ? 0 : Number(s);
14427
+ if (!isCalendarDay(year, month, day)) return void 0;
14428
+ const leap = hour === 23 && minute === 59 && second === 60;
14429
+ if (hour > 23 || minute > 59 || second > 59 && !leap) return void 0;
14430
+ const east = offsetMinutes(offset);
14431
+ if (east === void 0) return void 0;
14432
+ const millisecond = fraction === void 0 ? 0 : Number(fraction.slice(1, 4).padEnd(3, "0"));
14433
+ const wall = utcMilliseconds(year, month, day, hour, minute, leap ? 59 : second, millisecond);
14434
+ return instantOf(wall - east * 6e4 + (leap ? 1e3 - millisecond : 0));
14435
+ }
14436
+ function normalizeInstant(value) {
14437
+ if (typeof value !== "string") return void 0;
14438
+ const read = readInstantText(value, STORED_INSTANT);
14439
+ return read?.kind === "instant" ? read.instant : void 0;
14440
+ }
14441
+ var STORED_INSTANT, DAYS_IN_MONTH;
14442
+ var init_chunk_IJSOONHT = __esm({
14443
+ "../../domain/schema/dist/chunk-IJSOONHT.js"() {
14444
+ STORED_INSTANT = /^(\d{4})-(\d{2})-(\d{2})[Tt ](\d{2}):(\d{2}):(\d{2})(\.\d+)?([Zz]|[+-]\d{2}(?::?\d{2})?)$/;
14445
+ DAYS_IN_MONTH = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
14446
+ }
14447
+ });
14447
14448
  function sortDependencyLevels(nodes, dependencies) {
14448
14449
  const nodeSet = new Set(nodes);
14449
14450
  const dependents = /* @__PURE__ */ new Map();
@@ -14512,16 +14513,16 @@ function extractCycle(leftover, dependencies) {
14512
14513
  }
14513
14514
  function fieldsOfType(type) {
14514
14515
  const collected = [];
14515
- const visit3 = (members, path27, sections) => {
14516
+ const visit2 = (members, path27, sections) => {
14516
14517
  for (const [index, member] of members.entries()) {
14517
14518
  if (isSection(member)) {
14518
- visit3(member.fields, [...path27, index, "fields"], [...sections, member.id]);
14519
+ visit2(member.fields, [...path27, index, "fields"], [...sections, member.id]);
14519
14520
  } else {
14520
14521
  collected.push({ field: member, path: [...path27, index], sections });
14521
14522
  }
14522
14523
  }
14523
14524
  };
14524
- visit3(type.fields ?? [], ["fields"], []);
14525
+ visit2(type.fields ?? [], ["fields"], []);
14525
14526
  return collected;
14526
14527
  }
14527
14528
  function indexedFieldPath(path27) {
@@ -14807,12 +14808,12 @@ function filterCapabilitiesOf(kind) {
14807
14808
  return { filterable: filter.kind !== null, filterOperators: [...filter.viewOperators] };
14808
14809
  }
14809
14810
  var FallbackChainSchema, BaseFieldConfigSchema, ShortTextConfigSchema, LongTextConfigSchema, AI_INSTRUCTIONS_MAX_CHARS, AIConfigSchema, FieldAIConfigSchema, AssetAIConfigSchema, UNKNOWN_INPUT_MESSAGE, INPUT_CYCLE_MESSAGE, TagsConfigSchema, ofShapes, SHAPE_PLACE_WORDS, ListConfigSchema, ObjectConfigSchema, ReferenceStrengthSchema, OnTargetDeleteSchema, ReferenceTargetSchema, ReferenceConfigSchema, RichTextDefaultSchema, declaredShapes, RichTextLinksSchema, RichTextConfigSchema, TableConfigSchema, CodeConfigSchema, DOMAIN, EmailConfigSchema, UrlConfigSchema, SlugConfigSchema, IntegerConfigSchema, DecimalConfigSchema, BooleanConfigSchema, EnumConfigSchema, DATE_PATTERN, CalendarDateSchema, DateConfigSchema, InstantSchema, DateTimeConfigSchema, JsonValueSchema, count, bound, JsonFieldSchemaSchema, JsonConfigSchema, BaseUIConfigSchema, TextUIOptionsSchema, LongTextUIOptionsSchema, SlugUIOptionsSchema, NumericUIOptionsSchema, BooleanUIOptionsSchema, EnumUIOptionsSchema, DateUIOptionsSchema, DateTimeUIOptionsSchema, ReferenceUIOptionsSchema, TagsUIOptionsSchema, ListUIOptionsSchema, ObjectUIOptionsSchema, UI_OPTIONS_SCHEMAS, UIConfigSchema, RuleConditionSchema, RuleConditionsSchema, VisibilityRuleSchema, RequirementRuleSchema, ValidationRuleSchema, ReadOnlyRuleSchema, FieldRuleSchema, refuseALocaleList, LocalizationConfigSchema, INVALID_FIELD_CONFIG, judgingFieldConfigs, FieldSchema, FIELDSET_ID, TypeMemberSchema, FieldsetSchema, BUILT_IN_ROLES, ROLE_ACTIONS, RoleActionSchema, BuiltInRoleSchema, roleIdPattern, RoleIdSchema, accessTagPattern, AccessTagSchema, AccessTagsArraySchema, ResourcePermissionSchema, FieldVisibilitySchema, RolePermissionsSchema, RoleSchema, RolesArraySchema, COLUMN_RENDERERS, ColumnRendererSchema, FIELD_CAPABILITIES, SYSTEM_FIELD_CAPABILITIES, SYSTEM_FIELD_IDS, CHOICE_OPERATORS, PERSON_OPERATORS, INSTANT_OPERATORS, STUDIO_SYSTEM_FIELD_CAPABILITIES, STUDIO_SYSTEM_FIELD_IDS, FIELD_ICONS;
14810
- var init_chunk_GD7GMZ3T = __esm({
14811
- "../../domain/schema/dist/chunk-GD7GMZ3T.js"() {
14812
- init_chunk_IJSOONHT();
14811
+ var init_chunk_LO5JNU7O = __esm({
14812
+ "../../domain/schema/dist/chunk-LO5JNU7O.js"() {
14813
14813
  init_chunk_3VE5T7BO();
14814
14814
  init_chunk_DERETXFC();
14815
14815
  init_chunk_J57LV7E6();
14816
+ init_chunk_IJSOONHT();
14816
14817
  init_chunk_2GCFKBFW();
14817
14818
  FallbackChainSchema = z.object({
14818
14819
  chain: z.array(
@@ -14996,16 +14997,16 @@ var init_chunk_GD7GMZ3T = __esm({
14996
14997
  });
14997
14998
  }
14998
14999
  if (data.defaultValue !== void 0) {
14999
- const isMulti2 = data.multi === true;
15000
+ const isMulti3 = data.multi === true;
15000
15001
  const isArrayDefault = Array.isArray(data.defaultValue);
15001
- if (isMulti2 && !isArrayDefault) {
15002
+ if (isMulti3 && !isArrayDefault) {
15002
15003
  ctx.addIssue({
15003
15004
  code: z.ZodIssueCode.custom,
15004
15005
  message: "defaultValue must be an array when multi is true",
15005
15006
  path: ["defaultValue"]
15006
15007
  });
15007
15008
  }
15008
- if (!isMulti2 && isArrayDefault) {
15009
+ if (!isMulti3 && isArrayDefault) {
15009
15010
  ctx.addIssue({
15010
15011
  code: z.ZodIssueCode.custom,
15011
15012
  message: "defaultValue must be a string when multi is false or undefined",
@@ -15197,16 +15198,16 @@ var init_chunk_GD7GMZ3T = __esm({
15197
15198
  defaultValue: z.union([z.string(), z.array(z.string())]).optional()
15198
15199
  }).superRefine((data, ctx) => {
15199
15200
  if (data.defaultValue !== void 0) {
15200
- const isMulti2 = data.multi === true;
15201
+ const isMulti3 = data.multi === true;
15201
15202
  const isArrayDefault = Array.isArray(data.defaultValue);
15202
- if (isMulti2 && !isArrayDefault) {
15203
+ if (isMulti3 && !isArrayDefault) {
15203
15204
  ctx.addIssue({
15204
15205
  code: z.ZodIssueCode.custom,
15205
15206
  message: "defaultValue must be an array when multi is true",
15206
15207
  path: ["defaultValue"]
15207
15208
  });
15208
15209
  }
15209
- if (!isMulti2 && isArrayDefault) {
15210
+ if (!isMulti3 && isArrayDefault) {
15210
15211
  ctx.addIssue({
15211
15212
  code: z.ZodIssueCode.custom,
15212
15213
  message: "defaultValue must be a string when multi is false or undefined",
@@ -16193,9 +16194,9 @@ function inSidebarOrder(views) {
16193
16194
  ).map(({ view }) => view);
16194
16195
  }
16195
16196
  var stageIdPattern, WorkflowEscalationSchema, WorkflowAutoAssignSchema, WorkflowStageSchema, WorkflowConfigSchema, ContentTypeWorkflowSchema, ASSET_KINDS, FORBIDDEN_ASSET_TYPE_FIELD_TYPES, IMAGE_OUTPUT_FORMATS, IMAGE_FIT_MODES, CF_IMAGES_LIMITS, DEFAULT_IMAGE_SOURCE, FitSchema, OutputFormatSchema, ImageTransformSchema, ImageUploadConfigSchema, VideoUploadConfigSchema, FileUploadConfigSchema, ImageExifConfigSchema, VariantDefinitionSchema, ImageSourceConfigSchema, ImageKindConfigSchema, VideoPosterConfigSchema, VideoCaptionsConfigSchema, VideoDownloadConfigSchema, VideoWatermarkConfigSchema, VideoKindConfigSchema, FileScanConfigSchema, FileKindConfigSchema, AssetTypeSchema;
16196
- var init_chunk_UUBK4U6F = __esm({
16197
- "../../domain/schema/dist/chunk-UUBK4U6F.js"() {
16198
- init_chunk_GD7GMZ3T();
16197
+ var init_chunk_MYIZUEM5 = __esm({
16198
+ "../../domain/schema/dist/chunk-MYIZUEM5.js"() {
16199
+ init_chunk_LO5JNU7O();
16199
16200
  stageIdPattern = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*$|^[a-z][a-zA-Z0-9]*$/;
16200
16201
  WorkflowEscalationSchema = z.object({
16201
16202
  /** Roles to notify when stage times out */
@@ -16481,7 +16482,7 @@ function detectCircularFallback(startCode, locales) {
16481
16482
  const visited = /* @__PURE__ */ new Set();
16482
16483
  const path27 = [];
16483
16484
  const localeMap = new Map(locales.map((l) => [l.code, l]));
16484
- function visit3(code) {
16485
+ function visit2(code) {
16485
16486
  if (visited.has(code)) {
16486
16487
  const cycleStart = path27.indexOf(code);
16487
16488
  return [...path27.slice(cycleStart), code];
@@ -16493,14 +16494,14 @@ function detectCircularFallback(startCode, locales) {
16493
16494
  visited.add(code);
16494
16495
  path27.push(code);
16495
16496
  for (const fallbackCode of locale.fallback) {
16496
- const cycle = visit3(fallbackCode);
16497
+ const cycle = visit2(fallbackCode);
16497
16498
  if (cycle) return cycle;
16498
16499
  }
16499
16500
  path27.pop();
16500
16501
  visited.delete(code);
16501
16502
  return null;
16502
16503
  }
16503
- return visit3(startCode);
16504
+ return visit2(startCode);
16504
16505
  }
16505
16506
  var FILTER_OPERATORS, FilterOperatorSchema, TimeUnitSchema, RelativeDateValueSchema, BCP47LocaleCodePattern, TextDirectionSchema, LocaleDefinitionSchema, LocalesArraySchema;
16506
16507
  var init_chunk_N3KX4HE4 = __esm({
@@ -16790,11 +16791,11 @@ function filterValueWith(range, relativeDate) {
16790
16791
  ]);
16791
16792
  }
16792
16793
  var QUERY_BLOCKS, queryBlocksOf, QUERY_BLOCKS_SPELLED, queryRunsBlock, QUERY_FILTER_OPERATORS, isQueryFilterOperator, QUERY_FILTER_OPERATOR_NAMES, SPELLED, HAVING_RELATIVE_WINDOW_PROBLEM, FIELD_PATH, INCLUDE_MODIFIER_NAMES, INCLUDE_MODIFIERS, isIncludeModifier, AGGREGATE_OPERATORS, isAggregateOperator, AGGREGATE_OPERATOR_NAMES, MAX_SELECT_OPERATION_ARGUMENT, withoutArguments, SELECT_STRING_OPERATIONS, isSelectStringOperationName, SELECT_STRING_OPERATION_NAMES, OPERATION_SPELLING, NON_NEGATIVE_INTEGER, VIEW_SLUG_PATTERN, VIEW_SLUG_MESSAGE, SCHEMA_VIEW_FILTER_GROUP_REFUSAL, SAVED_VIEW_FILTER_GROUP_REFUSAL, RangeValueSchema, ColumnConfigSchema, MetadataFieldConfigSchema, MetadataLineConfigSchema, TableSettingsSchema, ViewScopeSchema, contentTypeScope, contentTypesScope, allScope, entryTypeScope, DeclaredViewScopeSchema, DeclaredFilterValueSchema, SchemaViewFilterSchema, SchemaViewDefinitionSchema;
16793
- var init_chunk_7C2WVSYB = __esm({
16794
- "../../domain/schema/dist/chunk-7C2WVSYB.js"() {
16794
+ var init_chunk_AIPXA3F2 = __esm({
16795
+ "../../domain/schema/dist/chunk-AIPXA3F2.js"() {
16795
16796
  init_chunk_ZS3ASPOM();
16796
16797
  init_chunk_N3KX4HE4();
16797
- init_chunk_GD7GMZ3T();
16798
+ init_chunk_LO5JNU7O();
16798
16799
  init_chunk_J57LV7E6();
16799
16800
  init_chunk_2GCFKBFW();
16800
16801
  QUERY_BLOCKS = ["fetch", "aggregate", "search"];
@@ -17395,13 +17396,13 @@ function undeclaredFieldTypeMessage(type) {
17395
17396
  return `Invalid field type '${type}'. Valid field types are: ${FIELD_KINDS.join(", ")}`;
17396
17397
  }
17397
17398
  var QUERY_ENDPOINT_SEGMENT, QUERY_ENDPOINT_PATTERN, QUERY_SYSTEM_FIELDS, isQuerySystemField, QUERY_STORAGE_PATH_PREFIX, QUERY_SYSTEM_ROOTS, QUERY_FILE_MEMBERS, SEARCH_SELECT_COLUMNS, isSearchSelectColumn, PARAMETER_EXPRESSION_SOURCE, parameterExpressionMatcher, ANCHORED_PARAMETER_EXPRESSION, parseDefault, parseParameterExpression, collectParameterExpressions, endpointPathParameters, ParameterExpressionStringSchema, QUERY_PARAMETER_TYPES, QueryParameterTypeSchema, QueryParameterScalarSchema, QueryParameterSchema, typeOfDefault, declareQueryParameters, SEARCH_SCORE_SORT_KEYS, isSearchScoreSortKey, FIELD, PATH, SPELLING, Refused, parseDynamicParameter, ParameterizedLimitSchema, ParameterizedOffsetSchema, ScalarSchema, RelativeWindowSchema, WhereOperatorObjectSchema, FilterOperatorObjectSchema, HavingOperatorObjectSchema, WhereValueSchema, WhereConditionSchema, SortConditionSchema, RELATIONSHIP_NAME, IncludeRelationshipSchema, IncludeDefinitionSchema, SelectMappingSchema, FilterDefinitionSchema, FullTextSearchSchema, ContentTypesSchema, SearchBlockSchema, AggregationMetricSchema, QueryCardinalitySchema, QueryCachePolicySchema, FetchBlockSchema, AggregateBlockSchema, IncludeSubQueriesSchema, QueryDefinitionSchema, CACHE_POLICY_STRING, normalizeQueryCachePolicy, CONTENT_API_ROUTE_SEGMENTS, RESERVED_TYPE_IDS, UNBUILT_STAGE_SETTINGS, ContentTypeSchema, SettingsGroupSchema, SchemaDefinitionSchema, SavedViewFilterSchema;
17398
- var init_chunk_FNS5FUIG = __esm({
17399
- "../../domain/schema/dist/chunk-FNS5FUIG.js"() {
17400
- init_chunk_UUBK4U6F();
17401
- init_chunk_7C2WVSYB();
17399
+ var init_chunk_JNNDHC4Z = __esm({
17400
+ "../../domain/schema/dist/chunk-JNNDHC4Z.js"() {
17401
+ init_chunk_MYIZUEM5();
17402
+ init_chunk_AIPXA3F2();
17402
17403
  init_chunk_LK3PZTVM();
17403
17404
  init_chunk_N3KX4HE4();
17404
- init_chunk_GD7GMZ3T();
17405
+ init_chunk_LO5JNU7O();
17405
17406
  init_chunk_3VE5T7BO();
17406
17407
  init_chunk_J57LV7E6();
17407
17408
  init_chunk_2GCFKBFW();
@@ -18791,7 +18792,7 @@ function schemaContentHash(schema) {
18791
18792
  if (!hasSchemaShape(schema)) {
18792
18793
  throw new Error("Failed to generate schema hash: Invalid schema provided for hashing");
18793
18794
  }
18794
- return objectHash(normalizeSchemaValue(schema), SCHEMA_HASH_OPTIONS);
18795
+ return objectHash22(normalizeSchemaValue(schema), SCHEMA_HASH_OPTIONS);
18795
18796
  }
18796
18797
  function buildReferenceGraph(reader) {
18797
18798
  const forward = {};
@@ -18826,8 +18827,8 @@ function buildReferenceGraph(reader) {
18826
18827
  return { forward, reverse };
18827
18828
  }
18828
18829
  var DEFINITION_SECTIONS, KEYED_SECTIONS, SCHEMA_HASH_OPTIONS;
18829
- var init_chunk_EXFMYQJK = __esm({
18830
- "../../domain/schema/dist/chunk-EXFMYQJK.js"() {
18830
+ var init_chunk_EAFIVKTE = __esm({
18831
+ "../../domain/schema/dist/chunk-EAFIVKTE.js"() {
18831
18832
  init_chunk_J57LV7E6();
18832
18833
  DEFINITION_SECTIONS = {
18833
18834
  locales: "list",
@@ -18851,7 +18852,7 @@ var init_chunk_NGOOYRLJ = __esm({
18851
18852
  }
18852
18853
  });
18853
18854
 
18854
- // ../../domain/schema/dist/chunk-JEZEW6IY.js
18855
+ // ../../domain/schema/dist/chunk-CMB5TABE.js
18855
18856
  function buildFieldPath(segments) {
18856
18857
  return segments.join(".");
18857
18858
  }
@@ -18877,7 +18878,7 @@ function getReferenceFieldRenderer(targetKind) {
18877
18878
  function nestedRichTextFieldsOf(field) {
18878
18879
  const nested = /* @__PURE__ */ new Map();
18879
18880
  const read = /* @__PURE__ */ new Set();
18880
- const visit3 = (holder) => {
18881
+ const visit2 = (holder) => {
18881
18882
  for (const shape of richTextShapesOf(holder).blocks) {
18882
18883
  if (read.has(shape.id)) continue;
18883
18884
  read.add(shape.id);
@@ -18886,10 +18887,10 @@ function nestedRichTextFieldsOf(field) {
18886
18887
  );
18887
18888
  if (richText.length === 0) continue;
18888
18889
  nested.set(shape.id, new Map(richText.map((member) => [member.id, member])));
18889
- for (const member of richText) visit3(member);
18890
+ for (const member of richText) visit2(member);
18890
18891
  }
18891
18892
  };
18892
- visit3(field);
18893
+ visit2(field);
18893
18894
  return nested;
18894
18895
  }
18895
18896
  function nestedRichTextNarrowingsOf(field) {
@@ -18996,11 +18997,11 @@ function ownConfigOf(field) {
18996
18997
  return typeof config === "object" && config !== null && !Array.isArray(config) ? { ...config } : {};
18997
18998
  }
18998
18999
  var DEFAULT_FIELD_ICON, FIELD_RENDERER_MAP, SYSTEM_FIELD_PRESENTATION, SchemaReader;
18999
- var init_chunk_JEZEW6IY = __esm({
19000
- "../../domain/schema/dist/chunk-JEZEW6IY.js"() {
19001
- init_chunk_UUBK4U6F();
19000
+ var init_chunk_CMB5TABE = __esm({
19001
+ "../../domain/schema/dist/chunk-CMB5TABE.js"() {
19002
+ init_chunk_MYIZUEM5();
19002
19003
  init_chunk_2E3WLFT6();
19003
- init_chunk_GD7GMZ3T();
19004
+ init_chunk_LO5JNU7O();
19004
19005
  init_chunk_J57LV7E6();
19005
19006
  init_chunk_2GCFKBFW();
19006
19007
  DEFAULT_FIELD_ICON = "circle";
@@ -19979,10 +19980,10 @@ var init_chunk_JEZEW6IY = __esm({
19979
19980
  */
19980
19981
  extractRawFieldsWithContext(contentType) {
19981
19982
  const result = [];
19982
- const visit3 = (members, fieldset) => {
19983
+ const visit2 = (members, fieldset) => {
19983
19984
  for (const member of members) {
19984
19985
  if (isSection(member)) {
19985
- visit3(member.fields, member);
19986
+ visit2(member.fields, member);
19986
19987
  } else if (fieldset) {
19987
19988
  result.push({
19988
19989
  field: member,
@@ -19994,7 +19995,7 @@ var init_chunk_JEZEW6IY = __esm({
19994
19995
  }
19995
19996
  }
19996
19997
  };
19997
- visit3(contentType.fields ?? []);
19998
+ visit2(contentType.fields ?? []);
19998
19999
  return result;
19999
20000
  }
20000
20001
  /**
@@ -20736,7 +20737,7 @@ var init_chunk_JEZEW6IY = __esm({
20736
20737
  }
20737
20738
  });
20738
20739
 
20739
- // ../../domain/schema/dist/chunk-7YJSJCQ4.js
20740
+ // ../../domain/schema/dist/chunk-CM6Q7MMB.js
20740
20741
  function flattenTypeFields(detail) {
20741
20742
  return detail?.fields ?? [];
20742
20743
  }
@@ -20744,14 +20745,14 @@ function buildTypeDetail(reader, typeId) {
20744
20745
  return reader.getAssetType(typeId) ?? reader.getContentTypeDetails(typeId);
20745
20746
  }
20746
20747
  var TABLE_SYSTEM_FIELD_KINDS;
20747
- var init_chunk_7YJSJCQ4 = __esm({
20748
- "../../domain/schema/dist/chunk-7YJSJCQ4.js"() {
20748
+ var init_chunk_CM6Q7MMB = __esm({
20749
+ "../../domain/schema/dist/chunk-CM6Q7MMB.js"() {
20749
20750
  init_chunk_NGOOYRLJ();
20750
- init_chunk_JEZEW6IY();
20751
+ init_chunk_CMB5TABE();
20751
20752
  init_chunk_2E3WLFT6();
20752
20753
  init_chunk_ZVQ22ULG();
20753
20754
  init_chunk_N3KX4HE4();
20754
- init_chunk_GD7GMZ3T();
20755
+ init_chunk_LO5JNU7O();
20755
20756
  init_chunk_J57LV7E6();
20756
20757
  init_chunk_2GCFKBFW();
20757
20758
  TABLE_SYSTEM_FIELD_KINDS = {
@@ -20821,10 +20822,10 @@ function buildSchemaIndex(schema) {
20821
20822
  for (const place of fieldsetPlacesOf(list.field)) {
20822
20823
  const shape = place.shape;
20823
20824
  if (enclosing.includes(shape.id)) continue;
20824
- const visit3 = (members, basePath) => {
20825
+ const visit2 = (members, basePath) => {
20825
20826
  for (const [memberIndex, member] of members.entries()) {
20826
20827
  if (isSection(member)) {
20827
- visit3(member.fields, `${basePath}[${memberIndex}].fields`);
20828
+ visit2(member.fields, `${basePath}[${memberIndex}].fields`);
20828
20829
  continue;
20829
20830
  }
20830
20831
  const indexed = {
@@ -20838,7 +20839,7 @@ function buildSchemaIndex(schema) {
20838
20839
  recordShapeFields(indexed, [...enclosing, shape.id]);
20839
20840
  }
20840
20841
  };
20841
- visit3(shape.fields, `${list.path}.${place.at}.fields`);
20842
+ visit2(shape.fields, `${list.path}.${place.at}.fields`);
20842
20843
  }
20843
20844
  };
20844
20845
  const recordFields = (container, ownerId, owner, context, basePath, fieldList, fieldset) => {
@@ -21612,9 +21613,15 @@ function sectionsOf2(members) {
21612
21613
  function isCrossVersionCheckCode(code) {
21613
21614
  return Object.hasOwn(CROSS_VERSION_CHECKS, code);
21614
21615
  }
21616
+ function tsFields(lines) {
21617
+ return ["fields: {", ...lines.map((line) => ` ${line}`), "}"].join("\n");
21618
+ }
21619
+ function propertyName(fieldId) {
21620
+ return /^[A-Za-z_$][\w$]*$/.test(fieldId) ? fieldId : `'${fieldId}'`;
21621
+ }
21615
21622
  function shapeLocalizationConflictsOf(members) {
21616
21623
  const conflicts = [];
21617
- const visit3 = (path27, placed, shapeStack) => {
21624
+ const visit2 = (path27, placed, shapeStack) => {
21618
21625
  const localized = placed.filter((entry) => isFieldLocalized(entry.field));
21619
21626
  if (localized.length > 0) {
21620
21627
  const shared = placed.filter((entry) => !isFieldLocalized(entry.field));
@@ -21643,11 +21650,11 @@ function shapeLocalizationConflictsOf(members) {
21643
21650
  }
21644
21651
  }
21645
21652
  }
21646
- for (const [id, group] of byId) visit3(`${path27}.${id}`, group, [...shapeStack, ...shapesHere]);
21653
+ for (const [id, group] of byId) visit2(`${path27}.${id}`, group, [...shapeStack, ...shapesHere]);
21647
21654
  };
21648
21655
  for (const member of fieldsOfMembers(members)) {
21649
21656
  const field = member;
21650
- visit3(field.id, [{ field, shape: null, at: field.id }], []);
21657
+ visit2(field.id, [{ field, shape: null, at: field.id }], []);
21651
21658
  }
21652
21659
  return conflicts;
21653
21660
  }
@@ -21687,12 +21694,12 @@ function findReverseRelationship(includeField, sourceContentType, index) {
21687
21694
  if (isKind(field.type, "reference")) {
21688
21695
  const allowedTypes = normalizeReferenceTargets(field.config?.to);
21689
21696
  if (allowedTypes.includes(sourceContentType)) {
21690
- const isMulti2 = field.config?.multi === true;
21697
+ const isMulti3 = field.config?.multi === true;
21691
21698
  return {
21692
21699
  found: true,
21693
21700
  reverseContentType: potentialContentType,
21694
21701
  reverseField: field.id,
21695
- isSingleRef: !isMulti2
21702
+ isSingleRef: !isMulti3
21696
21703
  };
21697
21704
  }
21698
21705
  }
@@ -21705,12 +21712,12 @@ function findReverseRelationship(includeField, sourceContentType, index) {
21705
21712
  if (isKind(field.type, "reference")) {
21706
21713
  const allowedTypes = normalizeReferenceTargets(field.config?.to);
21707
21714
  if (allowedTypes.includes(sourceContentType) && (contentTypeId === includeField || singularize(contentTypeId) === singularize(includeField))) {
21708
- const isMulti2 = field.config?.multi === true;
21715
+ const isMulti3 = field.config?.multi === true;
21709
21716
  return {
21710
21717
  found: true,
21711
21718
  reverseContentType: contentTypeId,
21712
21719
  reverseField: field.id,
21713
- isSingleRef: !isMulti2
21720
+ isSingleRef: !isMulti3
21714
21721
  };
21715
21722
  }
21716
21723
  }
@@ -21799,26 +21806,26 @@ function notComparedWarning(part, refusals) {
21799
21806
  var USAGE_CONTAINERS, BaseValidator, ValidationUtils, PROTOTYPE_MEMBER_NAMES, NamingValidator, StructuralValidator, nestedLists, slugUniqueness, referenceTargetsResolve, richTextLinkTargetsResolve, NO_CHECKS, FIELD_CONFIG_CHECKS, FIELD_KIND_RULES, FieldConfigValidator, CrossReferenceValidator, BASIC_KINDS, NUMERIC_KINDS, DATE_KINDS, FieldsetValidator, CONTENT_TYPE_PROPS, GROUP_PROPS, QUERY_BASIC_PROPS, QUERY_OPTIONAL_PROPS, QUERY_DSL_BLOCKS, LOCALE_PROPS, ROLE_PROPS, WORKFLOW_STAGE_PROPS, VIEW_PROPS, FIELDSET_PROPS, ASSET_TYPE_PROPS, ASSET_KIND_BLOCKS, ASSET_KIND_KEY_MARKER, FILE_LOCALIZATION_MARKER, FIELD_REQUIRED_CHANGE_KEY, RICH_TEXT_NARROWING_CHANGE_KEYS, RICH_TEXT_DECLARED_CHANGE_KEYS, FIELD_SHAPE_CHANGE_KEY, FIELD_OPTIONS_CHANGE_KEY, SchemaDiffer, ADDED_LABEL, CROSS_VERSION_CHECKS, CROSS_VERSION_CODES, EvolutionValidator, NAVIGATION_KINDS, HierarchicalContentValidator, FieldRulesValidator, LOCALIZATION_FRIENDLY_KINDS, LocalizationValidator, LocaleConfigValidator, RECOMMENDED_SETTINGS_KINDS, DISCOURAGED_SETTINGS_KINDS, SettingsGroupsValidator, CONFIGURATION_KINDS, NOT_A_KIND_CONFIGURATION_TYPES, SingletonContentTypesValidator, FORBIDDEN_TYPES, AssetTypesValidator, COUNTED_TEXT_KINDS, WIDGET_KINDS, SUGGESTED_WIDGETS, HIGH_BENEFIT_UI_KINDS, DESCRIBED_KINDS, FieldUIValidator, DslQueryValidator, SLUG_SOURCE_KINDS, COMPLEX_SETTINGS_KINDS, SIMPLE_KINDS, LOCALIZABLE_TEXT_KINDS, DataIntegrityValidator, RolesValidator, EVOLUTION_VALIDATOR_KEY, CROSS_VERSION_CHECKS_SKIPPED, ValidationPipeline, SchemaValidator, FIELD_SECTIONS, OPERATION_TIER, DEPLOY_VALIDATION_CONFIG;
21800
21807
  var init_dist3 = __esm({
21801
21808
  "../../domain/schema/dist/index.js"() {
21802
- init_chunk_FNS5FUIG();
21809
+ init_chunk_JNNDHC4Z();
21803
21810
  init_chunk_DFM7SN6U();
21804
21811
  init_chunk_G5JJDJ2X();
21805
- init_chunk_EXFMYQJK();
21806
- init_chunk_7YJSJCQ4();
21812
+ init_chunk_EAFIVKTE();
21813
+ init_chunk_CM6Q7MMB();
21807
21814
  init_chunk_NGOOYRLJ();
21808
- init_chunk_JEZEW6IY();
21809
- init_chunk_UUBK4U6F();
21815
+ init_chunk_CMB5TABE();
21816
+ init_chunk_MYIZUEM5();
21810
21817
  init_chunk_2E3WLFT6();
21811
21818
  init_chunk_ZVQ22ULG();
21812
- init_chunk_7C2WVSYB();
21813
- init_chunk_ZS3ASPOM();
21819
+ init_chunk_AIPXA3F2();
21814
21820
  init_chunk_LK3PZTVM();
21821
+ init_chunk_ZS3ASPOM();
21815
21822
  init_chunk_N3KX4HE4();
21816
- init_chunk_JH6U6ENN();
21817
- init_chunk_GD7GMZ3T();
21818
- init_chunk_IJSOONHT();
21823
+ init_chunk_LO5JNU7O();
21819
21824
  init_chunk_3VE5T7BO();
21820
21825
  init_chunk_DERETXFC();
21821
21826
  init_chunk_J57LV7E6();
21827
+ init_chunk_JH6U6ENN();
21828
+ init_chunk_IJSOONHT();
21822
21829
  init_chunk_2GCFKBFW();
21823
21830
  USAGE_CONTAINERS = [
21824
21831
  "contentTypes",
@@ -22608,7 +22615,7 @@ var init_dist3 = __esm({
22608
22615
  );
22609
22616
  return;
22610
22617
  }
22611
- const shape = objectHash(fieldset, { algorithm: "sha256" });
22618
+ const shape = objectHash22(fieldset, { algorithm: "sha256" });
22612
22619
  const declared = first.get(fieldset.id);
22613
22620
  if (declared === void 0) {
22614
22621
  first.set(fieldset.id, { place, shape });
@@ -22768,7 +22775,7 @@ var init_dist3 = __esm({
22768
22775
  }
22769
22776
  }
22770
22777
  validateFieldsetConsistency(fieldsets, basePath, result) {
22771
- const fieldsetSizes = fieldsets.map((fs15) => fs15.fields.length);
22778
+ const fieldsetSizes = fieldsets.map((fs14) => fs14.fields.length);
22772
22779
  const avgSize = fieldsetSizes.reduce((a, b) => a + b, 0) / fieldsetSizes.length;
22773
22780
  for (const fieldset of fieldsets) {
22774
22781
  const fieldsetPath = `${basePath}.fields.${fieldset.id}`;
@@ -23192,8 +23199,8 @@ var init_dist3 = __esm({
23192
23199
  const oldFieldsets = sectionsOf2(oldCt.fields ?? []);
23193
23200
  const newFieldsets = sectionsOf2(newCt.fields ?? []);
23194
23201
  if (oldFieldsets.length === 0 && newFieldsets.length === 0) return;
23195
- const oldMap = new Map(oldFieldsets.map((fs15) => [fs15.id, fs15]));
23196
- const newMap = new Map(newFieldsets.map((fs15) => [fs15.id, fs15]));
23202
+ const oldMap = new Map(oldFieldsets.map((fs14) => [fs14.id, fs14]));
23203
+ const newMap = new Map(newFieldsets.map((fs14) => [fs14.id, fs14]));
23197
23204
  for (const newFs of newFieldsets) {
23198
23205
  const oldFs = oldMap.get(newFs.id);
23199
23206
  if (oldFs) {
@@ -23664,14 +23671,11 @@ var init_dist3 = __esm({
23664
23671
  findings.push({
23665
23672
  message: `Field type cannot be changed after deployment: "${oldField.fieldId}" (${oldType} \u2192 ${newType})`,
23666
23673
  path: newField.path,
23667
- suggestion: `Use deprecation workflow:
23668
- \u250C\u2500 Correct approach
23669
- \u2502 fields:
23670
- \u2502 \u251C\u2500 ${oldField.fieldId}:
23671
- \u2502 \u2502 type: "${oldField.fieldType}"
23672
- \u2502 \u2502 deprecated: true # Mark old field as deprecated
23673
- \u2502 \u2514\u2500 ${oldField.fieldId}_v2:
23674
- \u2502 type: "${newField.fieldType}" # Create new field with correct type`
23674
+ suggestion: `Use deprecation workflow: keep the deployed field, mark it deprecated, and add one with the new type beside it:
23675
+ ${tsFields([
23676
+ `${propertyName(oldField.fieldId)}: fields.${oldType}({ \u2026its options, deprecated: true }),`,
23677
+ `${propertyName(`${oldField.fieldId}_v2`)}: fields.${newType}({ \u2026 }),`
23678
+ ])}`
23675
23679
  });
23676
23680
  }
23677
23681
  }
@@ -23689,14 +23693,14 @@ var init_dist3 = __esm({
23689
23693
  previous,
23690
23694
  contentTypeChange.name
23691
23695
  );
23692
- if (potentialOriginalField && !this.isFieldDeprecated(potentialOriginalField, next.schema, contentTypeChange.name)) {
23696
+ if (potentialOriginalField && !this.isFieldDeprecated(potentialOriginalField.id, next.schema, contentTypeChange.name)) {
23693
23697
  findings.push({
23694
- message: `Field '${addedFieldId}' appears to be a replacement for '${potentialOriginalField}'. Consider marking the original field as deprecated.`,
23695
- path: `contentTypes.${contentTypeChange.name}.fields.${potentialOriginalField}`,
23698
+ message: `Field '${addedFieldId}' appears to be a replacement for '${potentialOriginalField.id}'. Consider marking the original field as deprecated.`,
23699
+ path: `contentTypes.${contentTypeChange.name}.fields.${potentialOriginalField.id}`,
23696
23700
  suggestion: `Mark the original field as deprecated:
23697
- - id: "${potentialOriginalField}"
23698
- type: "..."
23699
- deprecated: true`
23701
+ ${tsFields([
23702
+ `${propertyName(potentialOriginalField.id)}: fields.${potentialOriginalField.type}({ \u2026its options, deprecated: true }),`
23703
+ ])}`
23700
23704
  });
23701
23705
  }
23702
23706
  }
@@ -23763,13 +23767,13 @@ var init_dist3 = __esm({
23763
23767
  });
23764
23768
  }
23765
23769
  };
23766
- const visit3 = (members, path27) => {
23770
+ const visit2 = (members, path27) => {
23767
23771
  for (const [index, member] of members.entries()) {
23768
- if (isSection(member)) visit3(member.fields, `${path27}[${index}].fields`);
23772
+ if (isSection(member)) visit2(member.fields, `${path27}[${index}].fields`);
23769
23773
  else record(member, `${path27}[${index}]`);
23770
23774
  }
23771
23775
  };
23772
- visit3(entity.fields ?? [], `${basePath}.fields`);
23776
+ visit2(entity.fields ?? [], `${basePath}.fields`);
23773
23777
  }
23774
23778
  /**
23775
23779
  * Finds potential original field for a new field (e.g., "price_v2" -> "price")
@@ -23783,7 +23787,7 @@ var init_dist3 = __esm({
23783
23787
  if (!contentType) {
23784
23788
  return null;
23785
23789
  }
23786
- return fieldsOfMembers(contentType.fields).some((field) => field.id === baseFieldId) ? baseFieldId : null;
23790
+ return fieldsOfMembers(contentType.fields).find((field) => field.id === baseFieldId) ?? null;
23787
23791
  }
23788
23792
  /**
23789
23793
  * Checks if a field is marked as deprecated in the schema
@@ -23827,7 +23831,7 @@ var init_dist3 = __esm({
23827
23831
  */
23828
23832
  validateFieldTypeConsistency(index, result) {
23829
23833
  const fieldTypeMap = /* @__PURE__ */ new Map();
23830
- const visit3 = (field, path27) => {
23834
+ const visit2 = (field, path27) => {
23831
23835
  const fieldId = field.id;
23832
23836
  if (fieldTypeMap.has(fieldId)) {
23833
23837
  const existing = fieldTypeMap.get(fieldId);
@@ -23846,7 +23850,7 @@ var init_dist3 = __esm({
23846
23850
  fieldTypeMap.set(fieldId, { type: field.type, path: path27 });
23847
23851
  }
23848
23852
  };
23849
- this.traverseFields(index, visit3, { includeShapeFields: false });
23853
+ this.traverseFields(index, visit2, { includeShapeFields: false });
23850
23854
  }
23851
23855
  validateNamingStability(index, result) {
23852
23856
  const checkForTempNaming = (name, path27) => {
@@ -29166,27 +29170,30 @@ function recommendationsFromMessages(messages) {
29166
29170
  if (messages === void 0) return [];
29167
29171
  return messages.filter((text) => text.startsWith("recommendation: ")).map((text) => text.slice("recommendation: ".length));
29168
29172
  }
29169
- function isAdaptationPlan(value) {
29173
+ function isManifestPlan(value) {
29170
29174
  if (typeof value !== "object" || value === null) return false;
29171
29175
  const plan = value;
29172
- return typeof plan.planId === "string" && Array.isArray(plan.changes) && Array.isArray(plan.refusals);
29176
+ return typeof plan.planId === "string" && Array.isArray(plan.areas) && Array.isArray(plan.refusals) && typeof plan.needsConfirmation === "boolean";
29173
29177
  }
29174
- function planBlockageOf(body) {
29175
- if (body?.error.code !== "RESOURCE_CONFLICT") return void 0;
29176
- const details = body.error.details;
29177
- if (typeof details !== "object" || details === null || !("blockage" in details)) return void 0;
29178
- const blockage = details.blockage;
29179
- if (typeof blockage !== "object" || blockage === null) return void 0;
29180
- const { kind, facts } = blockage;
29178
+ function deployPlanBlockageOf(body) {
29179
+ const { kind, facts } = blockageOf2(body) ?? {};
29181
29180
  if (typeof facts !== "object" || facts === null) return void 0;
29182
29181
  const { plan, confirmedPlanId } = facts;
29183
- if (!isAdaptationPlan(plan)) return void 0;
29184
- if (kind === "schema-plan-unconfirmed") return { kind, plan };
29185
- if (kind === "schema-plan-stale" && typeof confirmedPlanId === "string") {
29182
+ if (!isManifestPlan(plan)) return void 0;
29183
+ if (kind === "manifest-plan-unconfirmed") return { kind, plan };
29184
+ if (kind === "manifest-plan-stale" && typeof confirmedPlanId === "string") {
29186
29185
  return { kind, confirmedPlanId, plan };
29187
29186
  }
29188
29187
  return void 0;
29189
29188
  }
29189
+ function blockageOf2(body) {
29190
+ if (body?.error.code !== "RESOURCE_CONFLICT") return void 0;
29191
+ const details = body.error.details;
29192
+ if (typeof details !== "object" || details === null || !("blockage" in details)) return void 0;
29193
+ const blockage = details.blockage;
29194
+ if (typeof blockage !== "object" || blockage === null) return void 0;
29195
+ return blockage;
29196
+ }
29190
29197
  var init_manage_error = __esm({
29191
29198
  "src/api/manage-error.ts"() {
29192
29199
  init_dist2();
@@ -29359,6 +29366,20 @@ var init_manage = __esm({
29359
29366
  };
29360
29367
  }
29361
29368
  });
29369
+ function schemaEntryPaths() {
29370
+ return TS_SCHEMA_PATHS.map((entry) => `${RELYIO_DIR}/${entry}`);
29371
+ }
29372
+ function schemaAreaOf(plan) {
29373
+ return plan.areas.find((candidate) => candidate.area === "schema") ?? null;
29374
+ }
29375
+ var RELYIO_DIR, TS_SCHEMA_PATHS;
29376
+ var init_dist4 = __esm({
29377
+ "../../domain/manifest/dist/index.js"() {
29378
+ init_dist3();
29379
+ RELYIO_DIR = "relyio";
29380
+ TS_SCHEMA_PATHS = ["schema.ts", "schema/index.ts"];
29381
+ }
29382
+ });
29362
29383
 
29363
29384
  // src/api/schema.ts
29364
29385
  async function getSchemaStatus(projectId, branchId, localSchema) {
@@ -29369,22 +29390,10 @@ async function getSchemaStatus(projectId, branchId, localSchema) {
29369
29390
  )
29370
29391
  );
29371
29392
  }
29372
- async function deploySchema(projectId, branchId, localSchema, options) {
29393
+ async function getCurrentSchema(projectId, branchId) {
29373
29394
  return readPayload2(
29374
- await client_default.post(
29375
- `/projects/${projectId}/branches/${branchId}/schema/deploy`,
29376
- {
29377
- localSchema,
29378
- ...options
29379
- }
29380
- )
29381
- );
29382
- }
29383
- async function planSchema(projectId, branchId, localSchema) {
29384
- return readPayload2(
29385
- await client_default.post(
29386
- `/projects/${projectId}/branches/${branchId}/schema/plan`,
29387
- localSchema
29395
+ await client_default.get(
29396
+ `/projects/${projectId}/branches/${branchId}/schema`
29388
29397
  )
29389
29398
  );
29390
29399
  }
@@ -29395,461 +29404,86 @@ async function getAdaptationStatus(projectId, branchId) {
29395
29404
  )
29396
29405
  );
29397
29406
  }
29407
+ var schema_default;
29398
29408
  var init_schema = __esm({
29399
29409
  "src/api/schema.ts"() {
29400
29410
  init_client2();
29401
29411
  init_wire();
29402
- }
29403
- });
29404
- function declaredFieldsets() {
29405
- return { byId: /* @__PURE__ */ new Map() };
29406
- }
29407
- function isRecord6(value) {
29408
- return typeof value === "object" && value !== null && !Array.isArray(value);
29409
- }
29410
- function readYamlFieldsets(declared, file, value) {
29411
- if (!Array.isArray(value)) {
29412
- return [`Invalid format for '${YAML_FIELDSETS_KEY}': expected an array of fieldset definitions`];
29413
- }
29414
- const errors = [];
29415
- for (const [index, item] of value.entries()) {
29416
- if (!isRecord6(item) || typeof item.id !== "string" || item.id === "") {
29417
- errors.push(`Missing required 'id' field in ${YAML_FIELDSETS_KEY}[${index}]`);
29418
- continue;
29419
- }
29420
- const earlier = declared.byId.get(item.id);
29421
- if (earlier !== void 0) {
29422
- errors.push(
29423
- `${YAML_FIELDSETS_KEY} '${item.id}' is already declared in ${earlier.file}; an id is declared once`
29424
- );
29425
- continue;
29426
- }
29427
- declared.byId.set(item.id, { fieldset: item, file });
29428
- }
29429
- return errors;
29430
- }
29431
- function placeYamlFieldsets(schema, declared) {
29432
- const placed = [];
29433
- let errors = [];
29434
- const named2 = (id, at, stack) => {
29435
- if (typeof id !== "string" || id === "") {
29436
- errors.push(`${at}: 'fieldset' names a fieldset declared under '${YAML_FIELDSETS_KEY}'`);
29437
- return void 0;
29438
- }
29439
- const declaredAs = declared.byId.get(id);
29440
- if (declaredAs === void 0) {
29441
- errors.push(
29442
- `${at}: fieldset '${id}' is not declared under '${YAML_FIELDSETS_KEY}' in any schema file`
29443
- );
29444
- return void 0;
29445
- }
29446
- if (stack.includes(id)) {
29447
- errors.push(cycleMessage(id, [...stack, id], at));
29448
- return void 0;
29449
- }
29450
- const { fields, ...shape2 } = declaredAs.fieldset;
29451
- return {
29452
- ...structuredClone(shape2),
29453
- fields: place(structuredClone(fields), `${at}.fields`, [...stack, id])
29412
+ schema_default = {
29413
+ getSchemaStatus,
29414
+ getCurrentSchema,
29415
+ getAdaptationStatus
29454
29416
  };
29455
- };
29456
- const reference = (entry, at, stack) => {
29457
- const { fieldset: id, ...rest } = entry;
29458
- const extra = Object.keys(rest);
29459
- if (typeof id === "string" && id !== "" && extra.length > 0) {
29460
- errors.push(
29461
- `${at}: 'fieldset: ${id}' names a fieldset and holds nothing else; remove ${extra.map((key) => `'${key}'`).join(", ")}, or declare the fieldset here instead`
29462
- );
29463
- return entry;
29464
- }
29465
- return named2(id, at, stack) ?? entry;
29466
- };
29467
- const inPlace = (fieldset, at, stack) => {
29468
- const id = typeof fieldset.id === "string" ? fieldset.id : at;
29469
- return { ...fieldset, fields: place(fieldset.fields, `${at}.fields`, [...stack, id]) };
29470
- };
29471
- const shapes = (of, at, stack) => {
29472
- if (!Array.isArray(of)) return shape(of, at, stack);
29473
- if (of.length === 0) {
29474
- errors.push(`${at}: an 'of' names at least one fieldset`);
29475
- return of;
29476
- }
29477
- return of.map((each, index) => shape(each, `${at}[${index}]`, stack));
29478
- };
29479
- const shape = (of, at, stack) => {
29480
- if (typeof of === "string") return named2(of, at, stack) ?? of;
29481
- if (isRecord6(of) && "fieldset" in of) return reference(of, at, stack);
29482
- if (isRecord6(of) && !("type" in of) && Array.isArray(of.fields)) return inPlace(of, at, stack);
29483
- errors.push(
29484
- `${at}: an 'of' names a fieldset declared under '${YAML_FIELDSETS_KEY}', or declares one with an id, a displayName and fields`
29485
- );
29486
- return of;
29487
- };
29488
- function place(members, where, stack) {
29489
- if (!Array.isArray(members)) return members;
29490
- return members.map((member, index) => {
29491
- if (!isRecord6(member)) return member;
29492
- const at = `${where}[${index}]`;
29493
- if ("fieldset" in member) return reference(member, at, stack);
29494
- if (!("type" in member) && Array.isArray(member.fields)) return inPlace(member, at, stack);
29495
- if (isRecord6(member.config) && "of" in member.config) {
29496
- return {
29497
- ...member,
29498
- config: { ...member.config, of: shapes(member.config.of, `${at}.config.of`, stack) }
29499
- };
29500
- }
29501
- return member;
29502
- });
29503
29417
  }
29504
- for (const section of FIELDSET_HOLDERS) {
29505
- const items = schema[section];
29506
- if (!isRecord6(items)) continue;
29507
- for (const [typeId, item] of Object.entries(items)) {
29508
- if (!isRecord6(item)) continue;
29509
- if (!("fields" in item)) continue;
29510
- errors = [];
29511
- item.fields = place(item.fields, `${section}.${typeId}.fields`, []);
29512
- for (const error2 of errors) placed.push({ item: `${section}.${typeId}`, error: error2 });
29513
- }
29514
- }
29515
- return placed;
29516
- }
29517
- function cycleMessage(id, chain, at) {
29518
- const start = chain.indexOf(id);
29519
- return `${at}: fieldset '${id}' contains itself: ${chain.slice(start).join(" \u2192 ")}. A fieldset may hold other fieldsets, never itself.`;
29520
- }
29521
- function isYamlSection(key) {
29522
- return Object.hasOwn(DEFINITION_SECTIONS, key);
29523
- }
29524
- function isSectionShaped(section, shape) {
29525
- return DEFINITION_SECTIONS[section] === shape;
29526
- }
29527
- function parseYamlSchemaFiles(files) {
29528
- const errors = [];
29529
- const schema = emptyDefinition();
29530
- const declaredIn = /* @__PURE__ */ new Map();
29531
- const fieldsets = declaredFieldsets();
29532
- const readList = (file, section, items) => {
29533
- if (!Array.isArray(items)) {
29534
- errors.push({
29535
- file,
29536
- error: `Invalid format for '${section}': expected an array of ${LIST_ITEM_NOUN[section]} definitions`
29537
- });
29538
- return;
29539
- }
29540
- const [labelKey, ...otherKeys] = LIST_ITEM_KEYS[section];
29541
- for (const [index, item] of items.entries()) {
29542
- const listItem = item ?? {};
29543
- if (!listItem[labelKey]) {
29544
- errors.push({ file, error: `Missing required '${labelKey}' field in ${section}[${index}]` });
29545
- continue;
29546
- }
29547
- const missing = otherKeys.find((key) => !listItem[key]);
29548
- if (missing !== void 0) {
29549
- errors.push({
29550
- file,
29551
- error: `Missing required '${missing}' field in ${section}[${index}] (${String(listItem[labelKey])})`
29552
- });
29553
- }
29554
- }
29555
- const merged = schema[section] ?? [];
29556
- schema[section] = [...merged, ...items];
29557
- };
29558
- const readKeyed = (file, section, items) => {
29559
- if (!Array.isArray(items)) {
29560
- errors.push({ file, error: `Invalid format for '${section}': expected an array of items` });
29561
- return;
29562
- }
29563
- const record = schema[section] ?? {};
29564
- for (const item of items) {
29565
- const schemaItem = item ?? {};
29566
- if (!schemaItem.id) {
29567
- errors.push({ file, error: `Missing required 'id' field in ${section} item` });
29568
- continue;
29569
- }
29570
- const id = String(schemaItem.id);
29571
- const earlier = declaredIn.get(`${section}.${id}`);
29572
- if (earlier !== void 0) {
29573
- errors.push({
29574
- file,
29575
- error: `${section} '${id}' is already declared in ${earlier}; an id is declared once`
29576
- });
29577
- continue;
29578
- }
29579
- declaredIn.set(`${section}.${id}`, file);
29580
- const { id: _id, ...declared } = schemaItem;
29581
- record[id] = declared;
29582
- }
29583
- schema[section] = record;
29584
- };
29585
- const readObject = (file, section, value) => {
29586
- if (value === null || typeof value !== "object" || Array.isArray(value)) {
29587
- errors.push({
29588
- file,
29589
- error: `Invalid format for '${section}': expected an object with 'enabled' and 'stages'`
29590
- });
29591
- return;
29592
- }
29593
- const earlier = declaredIn.get(section);
29594
- if (earlier !== void 0) {
29595
- errors.push({
29596
- file,
29597
- error: `'${section}' is already declared in ${earlier}; a schema has one ${section}`
29598
- });
29599
- return;
29600
- }
29601
- declaredIn.set(section, file);
29602
- schema[section] = value;
29603
- };
29604
- for (const { path: file, content } of [...files].sort(byPath)) {
29605
- try {
29606
- const data = yaml2.load(content);
29607
- if (!data || typeof data !== "object" || Array.isArray(data)) {
29608
- errors.push({
29609
- file,
29610
- error: "Invalid YAML: file is empty or not a map of schema sections"
29611
- });
29612
- continue;
29613
- }
29614
- for (const [key, value] of Object.entries(data)) {
29615
- if (key === YAML_FIELDSETS_KEY) {
29616
- for (const error2 of readYamlFieldsets(fieldsets, file, value))
29617
- errors.push({ file, error: error2 });
29618
- continue;
29619
- }
29620
- if (!isYamlSection(key)) {
29621
- errors.push({
29622
- file,
29623
- error: `Unknown schema section '${key}'. A schema file's top-level keys are: ${[...Object.keys(DEFINITION_SECTIONS), YAML_FIELDSETS_KEY].join(", ")}`
29624
- });
29625
- continue;
29626
- }
29627
- if (isSectionShaped(key, "list")) readList(file, key, value);
29628
- else if (isSectionShaped(key, "keyed")) readKeyed(file, key, value);
29629
- else readObject(file, key, value);
29630
- }
29631
- } catch (error2) {
29632
- errors.push({
29633
- file,
29634
- error: error2 instanceof Error ? error2.message : "Unknown error while parsing file"
29635
- });
29636
- }
29637
- }
29638
- for (const { item, error: error2 } of placeYamlFieldsets(schema, fieldsets)) {
29639
- errors.push({ file: declaredIn.get(item) ?? item, error: error2 });
29640
- }
29641
- return { schema, errors };
29642
- }
29643
- function byPath(a, b) {
29644
- if (a.path < b.path) return -1;
29645
- return a.path > b.path ? 1 : 0;
29646
- }
29647
- function loadedAsSent(schema) {
29648
- return JSON.parse(JSON.stringify(schema));
29418
+ });
29419
+
29420
+ // src/api/manifest.ts
29421
+ async function planManifest(projectId, branchId, manifest) {
29422
+ return readPayload2(
29423
+ await client_default.post(
29424
+ `/projects/${projectId}/branches/${branchId}/manifest/plan`,
29425
+ { manifest }
29426
+ )
29427
+ );
29649
29428
  }
29650
- function sectionsShaped(shape) {
29651
- return Object.keys(DEFINITION_SECTIONS).filter(
29652
- (section) => DEFINITION_SECTIONS[section] === shape
29429
+ async function deployManifest(projectId, branchId, manifest, options = {}) {
29430
+ return readPayload2(
29431
+ await client_default.post(
29432
+ `/projects/${projectId}/branches/${branchId}/manifest/deploy`,
29433
+ { manifest, ...options }
29434
+ )
29653
29435
  );
29654
29436
  }
29655
- var YAML_FIELDSETS_KEY, FIELDSET_HOLDERS, LIST_ITEM_KEYS, LIST_ITEM_NOUN, RELYIO_DIR, TS_SCHEMA_PATHS, CONFIG_FILE_PATHS, YAML_SCHEMA_GLOB;
29656
- var init_dist4 = __esm({
29657
- "../schema-yaml/dist/index.js"() {
29658
- init_dist3();
29659
- YAML_FIELDSETS_KEY = "fieldsets";
29660
- FIELDSET_HOLDERS = [
29661
- "contentTypes",
29662
- "singletonContentTypes",
29663
- "assetTypes",
29664
- "settingsGroups"
29665
- ];
29666
- LIST_ITEM_KEYS = {
29667
- locales: ["code", "displayName"],
29668
- roles: ["id", "displayName"],
29669
- views: ["id", "name", "scope"]
29670
- };
29671
- LIST_ITEM_NOUN = {
29672
- locales: "locale",
29673
- roles: "role",
29674
- views: "view"
29675
- };
29676
- RELYIO_DIR = "relyio";
29677
- TS_SCHEMA_PATHS = ["schema.ts", "schema/index.ts"];
29678
- CONFIG_FILE_PATHS = [
29679
- "relyio.config.ts",
29680
- "relyio.config.js",
29681
- "relyio.config.mjs"
29682
- ];
29683
- YAML_SCHEMA_GLOB = "**/*.{yml,yaml}";
29684
- ({
29685
- stringType: Scalar.PLAIN,
29686
- indent: 2,
29687
- indentSeq: true,
29688
- flowConfig: false,
29689
- flowPadding: true
29690
- });
29691
- sectionsShaped("keyed");
29692
- sectionsShaped("object");
29437
+ var init_manifest = __esm({
29438
+ "src/api/manifest.ts"() {
29439
+ init_client2();
29440
+ init_wire();
29693
29441
  }
29694
29442
  });
29695
- async function loadRelyIOConfig(baseDir) {
29696
- for (const configPath of CONFIG_FILE_PATHS) {
29697
- const fullPath = path5.join(baseDir, configPath);
29698
- if (existsSync(fullPath)) {
29699
- try {
29700
- const __filename = fileURLToPath(import.meta.url);
29701
- const jiti = createJiti(__filename, {
29702
- interopDefault: true,
29703
- // Must stay OFF: jiti's module cache is process-global, so in a long-running process
29704
- // (`relyio dev`) a cached config would be re-served after edits. fsCache (content-hashed
29705
- // transpile cache) stays on for speed.
29706
- moduleCache: false,
29707
- extensions: [".ts", ".js", ".mjs", ".cjs", ".json"]
29708
- });
29709
- const configModule = await jiti.import(fullPath);
29710
- const config = configModule.default ?? configModule;
29711
- return config;
29712
- } catch (error2) {
29713
- console.error(
29714
- `Warning: Failed to load config file '${configPath}': ${error2 instanceof Error ? error2.message : String(error2)}`
29715
- );
29716
- return null;
29717
- }
29718
- }
29719
- }
29720
- return null;
29443
+ function schemaAsSent(schema) {
29444
+ return JSON.parse(JSON.stringify(schema));
29721
29445
  }
29722
- async function findTypeScriptSchema(relyioDir) {
29446
+ function findTypeScriptSchema(relyioDir) {
29723
29447
  for (const tsPath of TS_SCHEMA_PATHS) {
29724
29448
  const fullPath = path5.join(relyioDir, tsPath);
29725
- if (existsSync(fullPath)) {
29726
- return {
29727
- found: true,
29728
- path: fullPath,
29729
- description: `TypeScript schema at ${RELYIO_DIR}/${tsPath}`
29730
- };
29731
- }
29449
+ if (existsSync(fullPath)) return fullPath;
29732
29450
  }
29733
- return { found: false };
29451
+ return void 0;
29734
29452
  }
29735
- async function findYamlSchemas(relyioDir) {
29736
- try {
29737
- const yamlFiles = await glob(YAML_SCHEMA_GLOB, {
29738
- cwd: relyioDir,
29739
- withFileTypes: false
29740
- });
29741
- if (yamlFiles.length > 0) {
29742
- return {
29743
- found: true,
29744
- paths: yamlFiles.map((f) => path5.join(relyioDir, f)),
29745
- description: `YAML schema (${yamlFiles.length} file${yamlFiles.length === 1 ? "" : "s"})`
29746
- };
29747
- }
29748
- } catch {
29749
- }
29750
- return { found: false };
29453
+ async function findYamlFiles(relyioDir) {
29454
+ const found = await glob(YAML_FILE_GLOB, {
29455
+ cwd: relyioDir,
29456
+ posix: true,
29457
+ ignore: ["**/node_modules/**"]
29458
+ });
29459
+ return found.map((file) => `${RELYIO_DIR}/${file}`).sort();
29751
29460
  }
29752
29461
  async function detectSchemaSource(baseDir = process.cwd()) {
29753
29462
  const relyioDir = path5.join(baseDir, RELYIO_DIR);
29754
29463
  if (!existsSync(relyioDir)) {
29755
- return {
29756
- sourceType: null,
29757
- sourcePath: null,
29758
- description: `No '${RELYIO_DIR}' directory found`,
29759
- hasBothSources: false,
29760
- explicitlyConfigured: false
29761
- };
29762
- }
29763
- const config = await loadRelyIOConfig(baseDir);
29764
- const tsResult = await findTypeScriptSchema(relyioDir);
29765
- const yamlResult = await findYamlSchemas(relyioDir);
29766
- const hasBothSources = tsResult.found && yamlResult.found;
29767
- if (config?.schemaSource) {
29768
- if (config.schemaSource === "typescript") {
29769
- if (config.schemaPath) {
29770
- const customPath = path5.join(baseDir, config.schemaPath);
29771
- if (existsSync(customPath)) {
29772
- return {
29773
- sourceType: "typescript",
29774
- sourcePath: customPath,
29775
- description: `TypeScript schema at ${config.schemaPath} (configured)`,
29776
- hasBothSources,
29777
- typescriptPath: customPath,
29778
- yamlPaths: yamlResult.paths,
29779
- explicitlyConfigured: true
29780
- };
29781
- }
29782
- }
29783
- if (tsResult.found) {
29784
- return {
29785
- sourceType: "typescript",
29786
- sourcePath: tsResult.path,
29787
- description: `${tsResult.description} (configured)`,
29788
- hasBothSources,
29789
- typescriptPath: tsResult.path,
29790
- yamlPaths: yamlResult.paths,
29791
- explicitlyConfigured: true
29792
- };
29793
- }
29794
- return {
29795
- sourceType: null,
29796
- sourcePath: null,
29797
- description: "TypeScript schema configured but not found",
29798
- hasBothSources: false,
29799
- explicitlyConfigured: true
29800
- };
29801
- }
29802
- if (config.schemaSource === "yaml") {
29803
- if (yamlResult.found) {
29804
- return {
29805
- sourceType: "yaml",
29806
- sourcePath: yamlResult.paths,
29807
- description: `${yamlResult.description} (configured)`,
29808
- hasBothSources,
29809
- typescriptPath: tsResult.path,
29810
- yamlPaths: yamlResult.paths,
29811
- explicitlyConfigured: true
29812
- };
29813
- }
29814
- return {
29815
- sourceType: null,
29816
- sourcePath: null,
29817
- description: "YAML schema configured but not found",
29818
- hasBothSources: false,
29819
- explicitlyConfigured: true
29820
- };
29821
- }
29464
+ return { sourcePath: null, description: `No '${RELYIO_DIR}' directory found`, yamlFiles: [] };
29822
29465
  }
29823
- if (tsResult.found) {
29466
+ const sourcePath = findTypeScriptSchema(relyioDir);
29467
+ if (sourcePath !== void 0) {
29824
29468
  return {
29825
- sourceType: "typescript",
29826
- sourcePath: tsResult.path,
29827
- description: tsResult.description,
29828
- hasBothSources,
29829
- typescriptPath: tsResult.path,
29830
- yamlPaths: yamlResult.paths,
29831
- explicitlyConfigured: false
29832
- };
29833
- }
29834
- if (yamlResult.found) {
29835
- return {
29836
- sourceType: "yaml",
29837
- sourcePath: yamlResult.paths,
29838
- description: yamlResult.description,
29839
- hasBothSources,
29840
- typescriptPath: tsResult.path,
29841
- yamlPaths: yamlResult.paths,
29842
- explicitlyConfigured: false
29469
+ sourcePath,
29470
+ description: `TypeScript schema at ${relativeToProject(baseDir, sourcePath)}`,
29471
+ yamlFiles: []
29843
29472
  };
29844
29473
  }
29474
+ const yamlFiles = await findYamlFiles(relyioDir);
29845
29475
  return {
29846
- sourceType: null,
29847
29476
  sourcePath: null,
29848
- description: "No schema files found",
29849
- hasBothSources: false,
29850
- explicitlyConfigured: false
29477
+ description: yamlFiles.length > 0 ? `No TypeScript schema; ${countOf2(yamlFiles.length, "YAML file")} RelyIO does not read` : "No schema files found",
29478
+ yamlFiles
29851
29479
  };
29852
29480
  }
29481
+ function relativeToProject(baseDir, file) {
29482
+ return path5.relative(baseDir, file).split(path5.sep).join("/");
29483
+ }
29484
+ function countOf2(count2, noun) {
29485
+ return `${count2} ${noun}${count2 === 1 ? "" : "s"}`;
29486
+ }
29853
29487
  function isSchemaDefinition(obj) {
29854
29488
  return typeof obj === "object" && obj !== null && "_tag" in obj && obj._tag === "schema";
29855
29489
  }
@@ -29879,15 +29513,15 @@ function normalizeTypeScriptSchema(schemaDefinition) {
29879
29513
  Object.assign(sections, canonicalDefinition(stripped));
29880
29514
  return normalized;
29881
29515
  }
29882
- async function loadTypeScriptSchema(schemaPath, detection) {
29883
- const errors = [];
29884
- const warnings = [];
29885
- if (detection.hasBothSources && !detection.explicitlyConfigured) {
29886
- warnings.push({
29887
- message: "Both TypeScript and YAML schemas found. Using TypeScript schema.",
29888
- suggestion: "To suppress this warning, add schemaSource: 'typescript' to relyio.config.ts or remove unused schema files."
29889
- });
29890
- }
29516
+ function refusedLoad(schemaPath, error2) {
29517
+ return {
29518
+ schema: emptyDefinition(),
29519
+ errors: [{ file: schemaPath, error: error2 }],
29520
+ warnings: [],
29521
+ sourcePath: schemaPath
29522
+ };
29523
+ }
29524
+ async function loadTypeScriptSchema(schemaPath) {
29891
29525
  try {
29892
29526
  const __filename = fileURLToPath(import.meta.url);
29893
29527
  const jiti = createJiti(__filename, {
@@ -29909,116 +29543,45 @@ async function loadTypeScriptSchema(schemaPath, detection) {
29909
29543
  schemaDefinition = schemaModule.schema;
29910
29544
  } else if (schemaModule.default) {
29911
29545
  schemaDefinition = schemaModule.default;
29912
- } else {
29913
- if (isSchemaDefinition(schemaModule)) {
29914
- schemaDefinition = schemaModule;
29915
- }
29546
+ } else if (isSchemaDefinition(schemaModule)) {
29547
+ schemaDefinition = schemaModule;
29916
29548
  }
29917
29549
  if (!schemaDefinition) {
29918
- errors.push({
29919
- file: schemaPath,
29920
- error: "No 'schema' export found. Export your schema as: export const schema = defineSchema({ ... })"
29921
- });
29922
- return {
29923
- schema: emptyDefinition(),
29924
- errors,
29925
- warnings,
29926
- sourceType: "typescript",
29927
- sourcePath: schemaPath,
29928
- explicitlyConfigured: detection.explicitlyConfigured
29929
- };
29550
+ return refusedLoad(
29551
+ schemaPath,
29552
+ "No 'schema' export found. Export your schema as: export const schema = defineSchema({ ... })"
29553
+ );
29930
29554
  }
29931
- if (!isSchemaDefinition(schemaDefinition)) {
29932
- if (typeof schemaDefinition === "object" && schemaDefinition !== null) {
29933
- const schema2 = normalizeTypeScriptSchema(schemaDefinition);
29934
- return {
29935
- schema: schema2,
29936
- errors,
29937
- warnings,
29938
- sourceType: "typescript",
29939
- sourcePath: schemaPath,
29940
- explicitlyConfigured: detection.explicitlyConfigured
29941
- };
29942
- }
29943
- errors.push({
29944
- file: schemaPath,
29945
- error: "Invalid schema export. Use defineSchema() from @relyio/sdk/schema to create your schema."
29946
- });
29555
+ if (isSchemaDefinition(schemaDefinition) || typeof schemaDefinition === "object") {
29947
29556
  return {
29948
- schema: emptyDefinition(),
29949
- errors,
29950
- warnings,
29951
- sourceType: "typescript",
29952
- sourcePath: schemaPath,
29953
- explicitlyConfigured: detection.explicitlyConfigured
29557
+ schema: normalizeTypeScriptSchema(schemaDefinition),
29558
+ errors: [],
29559
+ warnings: [],
29560
+ sourcePath: schemaPath
29954
29561
  };
29955
29562
  }
29956
- const schema = normalizeTypeScriptSchema(schemaDefinition);
29957
- return {
29958
- schema,
29959
- errors,
29960
- warnings,
29961
- sourceType: "typescript",
29962
- sourcePath: schemaPath,
29963
- explicitlyConfigured: detection.explicitlyConfigured
29964
- };
29563
+ return refusedLoad(
29564
+ schemaPath,
29565
+ "Invalid schema export. Use defineSchema() from @relyio/sdk/schema to create your schema."
29566
+ );
29965
29567
  } catch (error2) {
29966
- errors.push({
29967
- file: schemaPath,
29968
- error: error2 instanceof Error ? error2.message : "Failed to load TypeScript schema"
29969
- });
29970
- return {
29971
- schema: emptyDefinition(),
29972
- errors,
29973
- warnings,
29974
- sourceType: "typescript",
29975
- sourcePath: schemaPath,
29976
- explicitlyConfigured: detection.explicitlyConfigured
29977
- };
29978
- }
29979
- }
29980
- async function loadYamlSchema(yamlFiles, detection) {
29981
- const errors = [];
29982
- const warnings = [];
29983
- if (detection.hasBothSources && !detection.explicitlyConfigured) {
29984
- warnings.push({
29985
- message: "Both TypeScript and YAML schemas found. Using YAML schema.",
29986
- suggestion: "To suppress this warning, add schemaSource: 'yaml' to relyio.config.ts or remove unused schema files."
29987
- });
29988
- }
29989
- const files = [];
29990
- for (const file of [...yamlFiles].sort()) {
29991
- try {
29992
- files.push({ path: file, content: await fs4.readFile(file, "utf8") });
29993
- } catch (error2) {
29994
- errors.push({
29995
- file,
29996
- error: error2 instanceof Error ? error2.message : "Unknown error while parsing file"
29997
- });
29998
- }
29568
+ return refusedLoad(
29569
+ schemaPath,
29570
+ error2 instanceof Error ? error2.message : "Failed to load TypeScript schema"
29571
+ );
29999
29572
  }
30000
- const parsed = parseYamlSchemaFiles(files);
30001
- errors.push(...parsed.errors);
30002
- return {
30003
- schema: parsed.schema,
30004
- errors,
30005
- warnings,
30006
- sourceType: "yaml",
30007
- sourcePath: yamlFiles,
30008
- explicitlyConfigured: detection.explicitlyConfigured
30009
- };
30010
29573
  }
30011
29574
  async function loadSchema(baseDir = process.cwd()) {
30012
29575
  const detection = await detectSchemaSource(baseDir);
30013
- if (!detection.sourceType || !detection.sourcePath) {
30014
- throw new SchemaNotFoundError(baseDir);
29576
+ if (detection.sourcePath === null) {
29577
+ throw new SchemaNotFoundError(baseDir, detection.yamlFiles);
30015
29578
  }
30016
- const result = detection.sourceType === "typescript" ? await loadTypeScriptSchema(detection.sourcePath, detection) : await loadYamlSchema(detection.sourcePath, detection);
29579
+ const result = await loadTypeScriptSchema(detection.sourcePath);
30017
29580
  appendParsedTypeErrors(result);
30018
29581
  return result;
30019
29582
  }
30020
29583
  function appendParsedTypeErrors(result) {
30021
- const parsed = parseSchemaDefinition(loadedAsSent(result.schema));
29584
+ const parsed = parseSchemaDefinition(schemaAsSent(result.schema));
30022
29585
  if (parsed.success) return;
30023
29586
  for (const error2 of parsed.errors) {
30024
29587
  result.errors.push({ file: error2.path, error: error2.message, source: "parse" });
@@ -30034,36 +29597,42 @@ async function getSchemaWatchPaths(baseDir = process.cwd()) {
30034
29597
  const relyioDir = path5.join(baseDir, RELYIO_DIR);
30035
29598
  return existsSync(relyioDir) ? [relyioDir] : [];
30036
29599
  }
30037
- var SCHEMA_FILE_RE, DECLARATION_FILE_RE, IGNORED_WATCH_DIR_RE, SchemaNotFoundError;
30038
- var init_schema_loader = __esm({
30039
- "src/utils/schema-loader.ts"() {
30040
- init_dist3();
30041
- init_dist4();
30042
- SCHEMA_FILE_RE = /\.(ts|mts|cts|js|mjs|cjs|json|ya?ml)$/i;
30043
- DECLARATION_FILE_RE = /\.d\.ts$/i;
30044
- IGNORED_WATCH_DIR_RE = /(^|[/\\])(node_modules|\.git|dist|\.next|\.turbo|coverage)([/\\]|$)/;
30045
- SchemaNotFoundError = class extends Error {
30046
- constructor(baseDir) {
30047
- const relyioDir = path5.join(baseDir, RELYIO_DIR);
30048
- const message = `
30049
- No schema found in ${relyioDir}
29600
+ function entryList() {
29601
+ return schemaEntryPaths().map((entry) => ` ${entry}`).join("\n");
29602
+ }
29603
+ function yamlOnlyMessage(baseDir, yamlFiles) {
29604
+ const shown = yamlFiles.slice(0, SHOWN_YAML_FILES).map((file) => ` ${file}`);
29605
+ const more = yamlFiles.length - shown.length;
29606
+ if (more > 0) shown.push(` \u2026 and ${countOf2(more, "more file")}`);
29607
+ return `
29608
+ No TypeScript schema in ${path5.join(baseDir, RELYIO_DIR)}. TypeScript is the only schema source: RelyIO reads a project's schema from one of
29609
+
29610
+ ${entryList()}
30050
29611
 
30051
- We looked for schemas in these locations:
29612
+ and no longer reads YAML. This project holds ${countOf2(yamlFiles.length, "YAML file")} RelyIO does not read:
30052
29613
 
30053
- TypeScript:
30054
- \u2717 ${RELYIO_DIR}/schema.ts
30055
- \u2717 ${RELYIO_DIR}/schema/index.ts
29614
+ ${shown.join("\n")}
30056
29615
 
30057
- YAML:
30058
- \u2717 ${RELYIO_DIR}/**/*.yaml
29616
+ Write the schema in ${schemaEntryPaths()[0]} with the define* functions from '@relyio/sdk/schema'.
29617
+
29618
+ \u{1F4DA} Documentation: https://docs.relyio.com/schemas
29619
+ `.trim();
29620
+ }
29621
+ function noSchemaMessage(relyioDir) {
29622
+ return `
29623
+ No schema found in ${relyioDir}
29624
+
29625
+ We looked for a TypeScript schema in:
29626
+
29627
+ ${schemaEntryPaths().map((entry) => ` \u2717 ${entry}`).join("\n")}
30059
29628
 
30060
29629
  \u{1F4D6} Quick Start:
30061
29630
 
30062
- Option 1: TypeScript Schema (recommended for type safety)
29631
+ Run: relyio init --example blog
30063
29632
 
30064
- Create ${RELYIO_DIR}/schema.ts:
29633
+ or create ${schemaEntryPaths()[0]}:
30065
29634
 
30066
- import { defineSchema, defineContentType, fields } from '@relyio/sdk/schema'
29635
+ import { defineSchema, defineContentType, defineLocale, fields } from '@relyio/sdk/schema'
30067
29636
 
30068
29637
  const blogPost = defineContentType({
30069
29638
  displayName: 'Blog Post',
@@ -30074,19 +29643,34 @@ We looked for schemas in these locations:
30074
29643
  })
30075
29644
 
30076
29645
  export const schema = defineSchema({
29646
+ locales: [defineLocale('en', { displayName: 'English', default: true })],
30077
29647
  contentTypes: { blogPost }
30078
29648
  })
30079
29649
 
30080
- Option 2: YAML Schema (recommended for GitOps)
30081
-
30082
- Run: relyio init --example blog
30083
-
30084
29650
  \u{1F4DA} Documentation: https://docs.relyio.com/schemas
30085
29651
  `.trim();
30086
- super(message);
29652
+ }
29653
+ var YAML_FILE_GLOB, SCHEMA_FILE_RE, DECLARATION_FILE_RE, IGNORED_WATCH_DIR_RE, SchemaNotFoundError, SHOWN_YAML_FILES;
29654
+ var init_schema_loader = __esm({
29655
+ "src/utils/schema-loader.ts"() {
29656
+ init_dist4();
29657
+ init_dist3();
29658
+ YAML_FILE_GLOB = "**/*.{yaml,yml}";
29659
+ SCHEMA_FILE_RE = /\.(ts|mts|cts|js|mjs|cjs|json)$/i;
29660
+ DECLARATION_FILE_RE = /\.d\.ts$/i;
29661
+ IGNORED_WATCH_DIR_RE = /(^|[/\\])(node_modules|\.git|dist|\.next|\.turbo|coverage)([/\\]|$)/;
29662
+ SchemaNotFoundError = class extends Error {
29663
+ /** The YAML files under `relyio/` the project holds instead, relative to its root. */
29664
+ yamlFiles;
29665
+ constructor(baseDir, yamlFiles = []) {
29666
+ super(
29667
+ yamlFiles.length > 0 ? yamlOnlyMessage(baseDir, yamlFiles) : noSchemaMessage(path5.join(baseDir, RELYIO_DIR))
29668
+ );
30087
29669
  this.name = "SchemaNotFoundError";
29670
+ this.yamlFiles = yamlFiles;
30088
29671
  }
30089
29672
  };
29673
+ SHOWN_YAML_FILES = 10;
30090
29674
  }
30091
29675
  });
30092
29676
  function isGitRepository() {
@@ -30211,20 +29795,6 @@ async function preview(options) {
30211
29795
  if (!resolved.ok) return resolved;
30212
29796
  const { projectId, branchId, branchName, branchCreated } = resolved;
30213
29797
  emit({ type: "phase", phase: "loading-schema" });
30214
- try {
30215
- const detection = await detectSchemaSource(options.projectRoot);
30216
- if (!detection.sourceType) {
30217
- return failed({ message: "No schema found in this project.", code: "SCHEMA_NOT_FOUND" });
30218
- }
30219
- } catch (error2) {
30220
- if (error2 instanceof SchemaNotFoundError) {
30221
- return failed({ message: error2.message, code: "SCHEMA_NOT_FOUND" });
30222
- }
30223
- return failed({
30224
- message: error2 instanceof Error ? error2.message : "Failed to detect schema source",
30225
- code: "UNKNOWN"
30226
- });
30227
- }
30228
29798
  let loaded;
30229
29799
  try {
30230
29800
  loaded = await loadSchema(options.projectRoot);
@@ -30264,9 +29834,9 @@ async function preview(options) {
30264
29834
  let plan = null;
30265
29835
  if (hasChanges) {
30266
29836
  try {
30267
- plan = await planSchema(projectId, branchId, loaded.schema);
29837
+ plan = await planManifest(projectId, branchId, { schema: loaded.schema });
30268
29838
  } catch (error2) {
30269
- return failed(extractApiError(error2, "Could not read the adaptation plan"));
29839
+ return failed(extractApiError(error2, "Could not read the plan"));
30270
29840
  }
30271
29841
  }
30272
29842
  const gitCommitSha = options.target?.gitCommitSha ?? (getCurrentGitCommitSha() || void 0);
@@ -30274,7 +29844,6 @@ async function preview(options) {
30274
29844
  branchName,
30275
29845
  branchId,
30276
29846
  branchCreated,
30277
- schemaSourceType: loaded.sourceType,
30278
29847
  schemaSourcePath: loaded.sourcePath,
30279
29848
  schemaLoaderWarnings,
30280
29849
  hasChanges,
@@ -30303,7 +29872,7 @@ async function run(options) {
30303
29872
  previewData = previewOutcome.preview;
30304
29873
  localSchema = previewOutcome.localSchema;
30305
29874
  }
30306
- if (!previewData.hasChanges) {
29875
+ if (!previewData.hasChanges && options.deployUnchanged !== true) {
30307
29876
  return { status: "no-changes", preview: previewData };
30308
29877
  }
30309
29878
  if (options.confirm) {
@@ -30322,16 +29891,21 @@ async function run(options) {
30322
29891
  preview: previewData
30323
29892
  };
30324
29893
  }
30325
- let deployResult;
29894
+ let deployed;
30326
29895
  try {
30327
- deployResult = await deploySchema(projectId, previewData.branchId, localSchema, {
30328
- notes: options.notes,
30329
- gitCommitSha: previewData.gitCommitSha,
30330
- ...options.deployMode ? { deployMode: options.deployMode } : {},
30331
- ...options.confirmPlan === void 0 ? {} : { confirmPlan: options.confirmPlan }
30332
- });
29896
+ deployed = await deployManifest(
29897
+ projectId,
29898
+ previewData.branchId,
29899
+ { schema: localSchema },
29900
+ {
29901
+ notes: options.notes,
29902
+ gitCommitSha: previewData.gitCommitSha,
29903
+ ...options.deployMode ? { deployMode: options.deployMode } : {},
29904
+ ...options.confirmPlan === void 0 ? {} : { confirmPlan: options.confirmPlan }
29905
+ }
29906
+ );
30333
29907
  } catch (error2) {
30334
- const blockage = planBlockageOf(manageErrorBody(error2));
29908
+ const blockage = deployPlanBlockageOf(manageErrorBody(error2));
30335
29909
  if (blockage) return { status: "plan-required", blockage, preview: previewData };
30336
29910
  return {
30337
29911
  status: "failed",
@@ -30344,9 +29918,11 @@ async function run(options) {
30344
29918
  emit({ type: "phase", phase: "verifying" });
30345
29919
  verified = await verifyDeploy(projectId, previewData.branchId, options.projectRoot);
30346
29920
  }
29921
+ const deployResult = deployed.schema;
30347
29922
  return {
30348
29923
  status: "deployed",
30349
29924
  deploymentId: deployResult.id,
29925
+ deployment: deployed.deployment,
30350
29926
  version: deployResult.version,
30351
29927
  durationMs: Date.now() - start,
30352
29928
  preview: previewData,
@@ -30447,6 +30023,7 @@ var init_deploy_service = __esm({
30447
30023
  "src/services/deploy.service.ts"() {
30448
30024
  init_config();
30449
30025
  init_schema();
30026
+ init_manifest();
30450
30027
  init_manage();
30451
30028
  init_manage_error();
30452
30029
  init_schema_loader();
@@ -30492,12 +30069,12 @@ function datasetLines(datasets) {
30492
30069
  const lines = [];
30493
30070
  for (const dataset of datasets) {
30494
30071
  lines.push(
30495
- ` ${" ".repeat(16)}${chalk10.gray(`dataset ${dataset.datasetId}: ${formatAdaptationCount(dataset.count)}`)}`
30072
+ ` ${" ".repeat(16)}${chalk12.gray(`dataset ${dataset.datasetId}: ${formatAdaptationCount(dataset.count)}`)}`
30496
30073
  );
30497
30074
  const { inherited } = dataset;
30498
30075
  if (inherited !== null) {
30499
30076
  lines.push(
30500
- ` ${" ".repeat(16)}${chalk10.gray(`dataset ${dataset.datasetId} inherits from ${inherited.sourceDatasetId}: ${formatAdaptationCount(inherited.count)}, left in ${inherited.sourceDatasetId}`)}`
30077
+ ` ${" ".repeat(16)}${chalk12.gray(`dataset ${dataset.datasetId} inherits from ${inherited.sourceDatasetId}: ${formatAdaptationCount(inherited.count)}, left in ${inherited.sourceDatasetId}`)}`
30501
30078
  );
30502
30079
  }
30503
30080
  }
@@ -30510,13 +30087,13 @@ function renameLines(change) {
30510
30087
  const to = probableRenameOf(change);
30511
30088
  if (to === null) return [];
30512
30089
  return [
30513
- ` ${" ".repeat(16)}${chalk10.yellow(`Looks like a rename: this deploy adds ${planPathLabel({ section: change.path.section, type: to })} with the same fields. The entries of "${change.path.type}" are archived, not moved to "${to}".`)}`
30090
+ ` ${" ".repeat(16)}${chalk12.yellow(`Looks like a rename: this deploy adds ${planPathLabel({ section: change.path.section, type: to })} with the same fields. The entries of "${change.path.type}" are archived, not moved to "${to}".`)}`
30514
30091
  ];
30515
30092
  }
30516
30093
  function changeLines(change) {
30517
30094
  const label = ACTION_COLOR[change.does](ACTION_LABEL[change.does].padEnd(16));
30518
30095
  return [
30519
- ` ${label}${chalk10.bold(planPathLabel(change.path))} ${chalk10.gray(formatAdaptationCount(change.total))}`,
30096
+ ` ${label}${chalk12.bold(planPathLabel(change.path))} ${chalk12.gray(formatAdaptationCount(change.total))}`,
30520
30097
  ` ${" ".repeat(16)}${change.says}`,
30521
30098
  ...renameLines(change),
30522
30099
  ...datasetLines(change.datasets)
@@ -30525,7 +30102,7 @@ function changeLines(change) {
30525
30102
  function residueLines(residue) {
30526
30103
  const label = ACTION_COLOR[residue.does](ACTION_LABEL[residue.does].padEnd(16));
30527
30104
  return [
30528
- ` ${label}${chalk10.bold(`${planPathLabel(residue.path)} (residue)`)} ${chalk10.gray(formatAdaptationCount(residue.total))}`,
30105
+ ` ${label}${chalk12.bold(`${planPathLabel(residue.path)} (residue)`)} ${chalk12.gray(formatAdaptationCount(residue.total))}`,
30529
30106
  ` ${" ".repeat(16)}${residue.says}`,
30530
30107
  ...datasetLines(residue.datasets)
30531
30108
  ];
@@ -30534,26 +30111,25 @@ function refusalLines(refusal2) {
30534
30111
  const counted = refusal2.code === "LIST_BELOW_MIN_ITEMS" ? "list" : "item";
30535
30112
  const items = refusal2.items === void 0 ? "" : `, ${plural2(refusal2.items, counted)}`;
30536
30113
  return [
30537
- ` ${chalk10.red("Refused".padEnd(16))}${chalk10.bold(planPathLabel(refusal2.path))} ${chalk10.gray(`${refusal2.code}, ${plural2(refusal2.entries, "entry", "entries")}${items}`)}`,
30114
+ ` ${chalk12.red("Refused".padEnd(16))}${chalk12.bold(planPathLabel(refusal2.path))} ${chalk12.gray(`${refusal2.code}, ${plural2(refusal2.entries, "entry", "entries")}${items}`)}`,
30538
30115
  ` ${" ".repeat(16)}${refusal2.message}`
30539
30116
  ];
30540
30117
  }
30541
30118
  function planHasContent(plan) {
30542
30119
  return plan.changes.length > 0 || plan.residue.length > 0 || plan.refusals.length > 0;
30543
30120
  }
30544
- function formatAdaptationPlan(plan) {
30545
- const lines = [chalk10.bold("Content adaptation plan")];
30121
+ function adaptationPlanLines(plan) {
30122
+ const lines = [chalk12.bold("Content adaptation plan")];
30546
30123
  if (!planHasContent(plan)) {
30547
- lines.push(chalk10.gray(" Changes no stored content."));
30124
+ lines.push(chalk12.gray(" Changes no stored content."));
30548
30125
  }
30549
30126
  for (const change of plan.changes) lines.push(...changeLines(change));
30550
30127
  for (const residue of plan.residue) lines.push(...residueLines(residue));
30551
30128
  if (plan.refusals.length > 0) {
30552
- lines.push("", chalk10.red.bold(`Refused: ${plural2(plan.refusals.length, "change")}`));
30129
+ lines.push("", chalk12.red.bold(`Refused: ${plural2(plan.refusals.length, "change")}`));
30553
30130
  for (const refusal2 of plan.refusals) lines.push(...refusalLines(refusal2));
30554
30131
  }
30555
- lines.push(chalk10.gray(` Plan ${plan.planId}`));
30556
- return lines.join("\n");
30132
+ return lines;
30557
30133
  }
30558
30134
  function summarizeAdaptationPlan(plan) {
30559
30135
  const parts = [
@@ -30580,19 +30156,41 @@ var init_adaptation_plan = __esm({
30580
30156
  "leaves-to-author": "Left to author"
30581
30157
  };
30582
30158
  ACTION_COLOR = {
30583
- deletes: chalk10.red,
30584
- archives: chalk10.yellow,
30585
- backfills: chalk10.cyan,
30586
- renames: chalk10.yellow,
30587
- nothing: chalk10.gray,
30588
- "leaves-to-author": chalk10.magenta
30159
+ deletes: chalk12.red,
30160
+ archives: chalk12.yellow,
30161
+ backfills: chalk12.cyan,
30162
+ renames: chalk12.yellow,
30163
+ nothing: chalk12.gray,
30164
+ "leaves-to-author": chalk12.magenta
30589
30165
  };
30590
30166
  }
30591
30167
  });
30168
+ function schemaPlanOf(plan) {
30169
+ const area = schemaAreaOf(plan);
30170
+ if (area === null) throw new Error(`Manage answered plan ${plan.planId} with no schema area`);
30171
+ return area.detail;
30172
+ }
30173
+ function deployPlanHasContent(plan) {
30174
+ return planHasContent(schemaPlanOf(plan));
30175
+ }
30176
+ function formatDeployPlan(plan) {
30177
+ return [...adaptationPlanLines(schemaPlanOf(plan)), chalk12.gray(` Plan ${plan.planId}`)].join(
30178
+ "\n"
30179
+ );
30180
+ }
30181
+ function summarizeDeployPlan(plan) {
30182
+ return summarizeAdaptationPlan(schemaPlanOf(plan));
30183
+ }
30184
+ var init_deploy_plan = __esm({
30185
+ "src/utils/deploy-plan.ts"() {
30186
+ init_dist4();
30187
+ init_adaptation_plan();
30188
+ }
30189
+ });
30592
30190
 
30593
30191
  // ../codegen-core/dist/chunk-T7GG2PZC.js
30594
- function registerPlugin(language, load3) {
30595
- registeredPlugins.set(language, load3);
30192
+ function registerPlugin(language, load2) {
30193
+ registeredPlugins.set(language, load2);
30596
30194
  }
30597
30195
  function registeredLanguages() {
30598
30196
  return [...registeredPlugins.keys()].sort((a, b) => a.localeCompare(b));
@@ -30649,12 +30247,12 @@ var init_dist5 = __esm({
30649
30247
  }
30650
30248
  });
30651
30249
 
30652
- // ../codegen-typescript/dist/chunk-NLDHBBXF.js
30653
- function isRecord7(value) {
30250
+ // ../codegen-typescript/dist/chunk-MIVMGNUR.js
30251
+ function isRecord6(value) {
30654
30252
  return typeof value === "object" && value !== null && !Array.isArray(value);
30655
30253
  }
30656
30254
  function recordOf(value) {
30657
- return isRecord7(value) ? value : {};
30255
+ return isRecord6(value) ? value : {};
30658
30256
  }
30659
30257
  function isString(value) {
30660
30258
  return typeof value === "string";
@@ -30749,8 +30347,8 @@ function collectFieldsets(elements) {
30749
30347
  return collected;
30750
30348
  }
30751
30349
  var SchemaParser, SchemaValidator2, IDENTITY_KEYS, KEYED_FIELD_OPTIONS, CONFIG_WRITTEN_AS, TypeScriptGenerator, SCHEMA_PRINT_OPTIONS;
30752
- var init_chunk_NLDHBBXF = __esm({
30753
- "../codegen-typescript/dist/chunk-NLDHBBXF.js"() {
30350
+ var init_chunk_MIVMGNUR = __esm({
30351
+ "../codegen-typescript/dist/chunk-MIVMGNUR.js"() {
30754
30352
  init_dist3();
30755
30353
  init_dist5();
30756
30354
  init_dist3();
@@ -30760,7 +30358,7 @@ var init_chunk_NLDHBBXF = __esm({
30760
30358
  */
30761
30359
  parse(rawSchema) {
30762
30360
  const root = recordOf(rawSchema);
30763
- const schema = isRecord7(root.data) ? root.data : root;
30361
+ const schema = isRecord6(root.data) ? root.data : root;
30764
30362
  return {
30765
30363
  contentTypes: this.parseContentTypes(schema.contentTypes),
30766
30364
  singletons: this.parseSingletons(schema.singletonContentTypes),
@@ -30778,7 +30376,7 @@ var init_chunk_NLDHBBXF = __esm({
30778
30376
  * when it is not a list of objects: written back as no list, it would deploy as none.
30779
30377
  */
30780
30378
  parseList(list, key) {
30781
- if (!Array.isArray(list) || !list.every((item) => isRecord7(item))) {
30379
+ if (!Array.isArray(list) || !list.every((item) => isRecord6(item))) {
30782
30380
  throw new Error(
30783
30381
  `The schema's '${key}' is not a list of objects, which relyio generate-types cannot write back: ${JSON.stringify(list)}`
30784
30382
  );
@@ -30787,7 +30385,7 @@ var init_chunk_NLDHBBXF = __esm({
30787
30385
  }
30788
30386
  /** The workflow, as it is declared. */
30789
30387
  parseWorkflow(workflow) {
30790
- if (!isRecord7(workflow)) {
30388
+ if (!isRecord6(workflow)) {
30791
30389
  throw new Error(
30792
30390
  `The schema's 'workflow' is not an object, which relyio generate-types cannot write back: ${JSON.stringify(workflow)}`
30793
30391
  );
@@ -30811,7 +30409,7 @@ var init_chunk_NLDHBBXF = __esm({
30811
30409
  parseAssetType(id, assetType) {
30812
30410
  const raw = recordOf(assetType);
30813
30411
  const image = raw.image;
30814
- const variantIds = isRecord7(image) && Array.isArray(image.variants) ? image.variants.map((variant) => isRecord7(variant) ? variant.id : void 0).filter((vid) => typeof vid === "string" && vid.length > 0) : void 0;
30412
+ const variantIds = isRecord6(image) && Array.isArray(image.variants) ? image.variants.map((variant) => isRecord6(variant) ? variant.id : void 0).filter((vid) => typeof vid === "string" && vid.length > 0) : void 0;
30815
30413
  return {
30816
30414
  id,
30817
30415
  displayName: stringProp(raw, "displayName"),
@@ -30902,7 +30500,7 @@ var init_chunk_NLDHBBXF = __esm({
30902
30500
  }
30903
30501
  }
30904
30502
  if (type.key === "enum" && Array.isArray(config.options)) {
30905
- parsed.enumValues = config.options.map((option) => isRecord7(option) ? option.value : void 0).filter((value) => isString(value));
30503
+ parsed.enumValues = config.options.map((option) => isRecord6(option) ? option.value : void 0).filter((value) => isString(value));
30906
30504
  }
30907
30505
  const shapes = shapePlacesOf({ id: parsed.id, type: type.key ?? "", config });
30908
30506
  if (shapes.length > 0) {
@@ -31171,6 +30769,10 @@ ${prefix}: ${error2.path}`, ` ${error2.message}`);
31171
30769
  * how `relyio ci check` tells committed types that match the schema from stale ones (REL-1196).
31172
30770
  */
31173
30771
  addHeader() {
30772
+ if (this.options.purpose === "export") {
30773
+ this.addExportHeader();
30774
+ return;
30775
+ }
31174
30776
  this.output.push(`/**
31175
30777
  * \u{1F680} AUTO-GENERATED SDK SCHEMA FROM RELYIO
31176
30778
  *
@@ -31188,6 +30790,27 @@ ${prefix}: ${error2.path}`, ` ${error2.message}`);
31188
30790
  ${this.usageExample().map((line) => line ? ` * ${line}` : " *").join("\n")}
31189
30791
  * \`\`\`
31190
30792
  */
30793
+ `);
30794
+ }
30795
+ /**
30796
+ * The Export's header (spec 0 M6, REL-3720): the file is the project's schema source from now on,
30797
+ * written once from Production's schema and edited by its team, so it says so — never "generated,
30798
+ * do not edit". No clock reading and no hash, for the reason {@link addHeader} gives.
30799
+ */
30800
+ addExportHeader() {
30801
+ this.output.push(`/**
30802
+ * The schema of this project, written by RelyIO from what Production held when the project moved to
30803
+ * Repo mode.
30804
+ *
30805
+ * This file is the schema source of this project now. Edit it, open a pull request, and the RelyIO
30806
+ * check plans the change; once it merges, your default branch's \`relyio ci\` deploys it. A change
30807
+ * asked of the RelyIO Agent arrives as a pull request against it.
30808
+ *
30809
+ * It registers its schema with the SDK, so \`createClient\` is typed by it:
30810
+ * \`\`\`typescript
30811
+ ${this.usageExample().map((line) => line ? ` * ${line}` : " *").join("\n")}
30812
+ * \`\`\`
30813
+ */
31191
30814
  `);
31192
30815
  }
31193
30816
  /**
@@ -32061,6 +31684,7 @@ var dist_exports = {};
32061
31684
  __export(dist_exports, {
32062
31685
  TypeScriptGenerator: () => TypeScriptGenerator,
32063
31686
  default: () => index_default,
31687
+ exportSchemaSource: () => exportSchemaSource,
32064
31688
  formatWithPrettier: () => formatWithPrettier,
32065
31689
  generateTypeScript: () => generateTypeScript2,
32066
31690
  generateTypeScriptFromSchema: () => generateTypeScriptFromSchema2,
@@ -32073,10 +31697,13 @@ async function generateTypeScript2(rawSchema, options = {}) {
32073
31697
  async function generateTypeScriptFromSchema2(rawSchema, options = {}) {
32074
31698
  return generateTypeScriptFromSchema(rawSchema, options, formatWithPrettier);
32075
31699
  }
31700
+ async function exportSchemaSource(definition) {
31701
+ return generateTypeScript2({ data: definition }, { purpose: "export" });
31702
+ }
32076
31703
  var formatWithPrettier, plugin, index_default;
32077
31704
  var init_dist6 = __esm({
32078
31705
  "../codegen-typescript/dist/index.js"() {
32079
- init_chunk_NLDHBBXF();
31706
+ init_chunk_MIVMGNUR();
32080
31707
  formatWithPrettier = async (source) => {
32081
31708
  try {
32082
31709
  return await format(source, SCHEMA_PRINT_OPTIONS);
@@ -32209,7 +31836,7 @@ function referenceOf(field, to, scope) {
32209
31836
  }
32210
31837
  return `Union[${["str", ...targets.map((target) => scope.entry(target, field))].join(", ")}]`;
32211
31838
  }
32212
- function isRecord8(value) {
31839
+ function isRecord7(value) {
32213
31840
  return value !== null && typeof value === "object" && !Array.isArray(value);
32214
31841
  }
32215
31842
  function arrayAt(field, key) {
@@ -32248,7 +31875,7 @@ function jsonSchemaClasses(schema, name, doc, naming3) {
32248
31875
  return { annotation, classes };
32249
31876
  }
32250
31877
  function jsonSchemaType(schema, name, doc, naming3, classes) {
32251
- if (!isRecord8(schema)) return "Any";
31878
+ if (!isRecord7(schema)) return "Any";
32252
31879
  if (typeof schema.$ref === "string") return naming3.ref?.(schema.$ref) ?? "Any";
32253
31880
  if (Object.hasOwn(schema, "const")) return literalsOf([schema.const]);
32254
31881
  if (Array.isArray(schema.enum)) return literalsOf(schema.enum);
@@ -32302,10 +31929,10 @@ function jsonType(type, schema, name, doc, naming3, classes) {
32302
31929
  return `List[${item}]`;
32303
31930
  }
32304
31931
  case "object": {
32305
- const properties = isRecord8(schema.properties) ? Object.entries(schema.properties) : [];
31932
+ const properties = isRecord7(schema.properties) ? Object.entries(schema.properties) : [];
32306
31933
  if (properties.length > 0) return objectClass(schema, properties, name, doc, naming3, classes);
32307
31934
  const additional = schema.additionalProperties;
32308
- if (!isRecord8(additional)) return "Dict[str, Any]";
31935
+ if (!isRecord7(additional)) return "Dict[str, Any]";
32309
31936
  const value = jsonSchemaType(
32310
31937
  additional,
32311
31938
  `${name}Value`,
@@ -32348,7 +31975,7 @@ function pythonTypeOf(field, kind, scope) {
32348
31975
  return ROWS[kind](field, scope);
32349
31976
  }
32350
31977
  function pythonWriteTypeOf(field, kind, scope) {
32351
- if (kind === "reference") return isMulti(field) ? "List[str]" : "Optional[str]";
31978
+ if (kind === "reference") return isMulti2(field) ? "List[str]" : "Optional[str]";
32352
31979
  return pythonTypeOf(field, kind, {
32353
31980
  ...scope,
32354
31981
  shape: (shapeId) => scope.writeShape(shapeId),
@@ -32418,7 +32045,7 @@ function asSchemaField(value, path27, warnings) {
32418
32045
  const config = isRecord22(value.config) ? value.config : void 0;
32419
32046
  return { id: value.id, type: value.type, required: config?.required === true, config };
32420
32047
  }
32421
- function fieldsOf(raw, path27, warnings) {
32048
+ function fieldsOf2(raw, path27, warnings) {
32422
32049
  const flatten = (members) => Array.isArray(members) ? members.flatMap(
32423
32050
  (member) => isRecord22(member) && !("type" in member) && Array.isArray(member.fields) ? flatten(member.fields) : [member]
32424
32051
  ) : [];
@@ -32432,7 +32059,7 @@ function elementsOf(ir, kind, warnings) {
32432
32059
  return {
32433
32060
  id,
32434
32061
  displayName: typeof element.displayName === "string" ? element.displayName : void 0,
32435
- fields: fieldsOf(element, id, warnings)
32062
+ fields: fieldsOf2(element, id, warnings)
32436
32063
  };
32437
32064
  });
32438
32065
  }
@@ -32696,7 +32323,7 @@ function shapesIn(ir, warnings) {
32696
32323
  shapes.set(shape.id, {
32697
32324
  id: shape.id,
32698
32325
  displayName: typeof raw.displayName === "string" ? raw.displayName : void 0,
32699
- fields: fieldsOf(raw, `${path27}.${member.id}`, warnings),
32326
+ fields: fieldsOf2(raw, `${path27}.${member.id}`, warnings),
32700
32327
  at: `${path27}.${member.id}`
32701
32328
  });
32702
32329
  visitMembers(shape.fields, `${path27}.${member.id}`);
@@ -32884,7 +32511,7 @@ def to_json(instance: Any, indent: Optional[int] = None) -> str:
32884
32511
 
32885
32512
  ${exportList(["validate_data", "to_dict", "to_json"])}`;
32886
32513
  }
32887
- var define_RELYIO_READ_BLOCK_SCHEMAS_default, PYTHON_KEYWORDS, SHADOWED_IN_CLASS_BODY, MODEL_MEMBERS, MODEL_NAMESPACE, IMPORTED_NAMES, escape, always, sometimes, union, keyed, RICH_TEXT_NODES, isMulti, ROWS, READ_BLOCKS_MODULE, REF_PREFIX, ASSET_FILE, KINDS, TARGET_KINDS, RICH_TEXT_MODULE, FIELDSETS, ALIAS_SUFFIX, ModuleWriter, RESOLVE_POSTPONED_ANNOTATIONS, plugin2, index_default2;
32514
+ var define_RELYIO_READ_BLOCK_SCHEMAS_default, PYTHON_KEYWORDS, SHADOWED_IN_CLASS_BODY, MODEL_MEMBERS, MODEL_NAMESPACE, IMPORTED_NAMES, escape, always, sometimes, union, keyed, RICH_TEXT_NODES, isMulti2, ROWS, READ_BLOCKS_MODULE, REF_PREFIX, ASSET_FILE, KINDS, TARGET_KINDS, RICH_TEXT_MODULE, FIELDSETS, ALIAS_SUFFIX, ModuleWriter, RESOLVE_POSTPONED_ANNOTATIONS, plugin2, index_default2;
32888
32515
  var init_dist7 = __esm({
32889
32516
  "../codegen-python/dist/index.js"() {
32890
32517
  init_dist5();
@@ -33145,7 +32772,7 @@ var init_dist7 = __esm({
33145
32772
  }
33146
32773
  }
33147
32774
  };
33148
- isMulti = (field) => field.config?.multi === true;
32775
+ isMulti2 = (field) => field.config?.multi === true;
33149
32776
  ROWS = {
33150
32777
  shortText: () => "str",
33151
32778
  longText: () => "str",
@@ -33162,16 +32789,16 @@ var init_dist7 = __esm({
33162
32789
  decimal: () => "float",
33163
32790
  boolean: () => "bool",
33164
32791
  enum: (field) => {
33165
- const values = arrayAt(field, "options").map((option) => isRecord8(option) ? option.value : void 0).filter((value) => typeof value === "string");
32792
+ const values = arrayAt(field, "options").map((option) => isRecord7(option) ? option.value : void 0).filter((value) => typeof value === "string");
33166
32793
  const one = values.length > 0 ? `Literal[${values.map((value) => pyString(value)).join(", ")}]` : "str";
33167
- return isMulti(field) ? `List[${one}]` : one;
32794
+ return isMulti2(field) ? `List[${one}]` : one;
33168
32795
  },
33169
32796
  date: () => "str",
33170
32797
  dateTime: () => "str",
33171
32798
  // A single reference whose target was deleted under `onTargetDelete: 'nullify'` reads as null
33172
32799
  reference: (field, scope) => {
33173
32800
  const one = referenceOf(field, field.config?.to, scope);
33174
- return isMulti(field) ? `List[${one}]` : `Optional[${one}]`;
32801
+ return isMulti2(field) ? `List[${one}]` : `Optional[${one}]`;
33175
32802
  },
33176
32803
  tags: () => "List[str]",
33177
32804
  // A list of a shape (`of`, REL-1796) is a list of its items, each its fieldset's class; a page
@@ -33529,20 +33156,6 @@ async function runLocalVsRemote(options) {
33529
33156
  });
33530
33157
  }
33531
33158
  emit({ type: "phase", phase: "loading-schema" });
33532
- try {
33533
- const detection = await detectSchemaSource();
33534
- if (!detection.sourceType) {
33535
- return failed2({ message: "No schema found in this project.", code: "SCHEMA_NOT_FOUND" });
33536
- }
33537
- } catch (error2) {
33538
- if (error2 instanceof SchemaNotFoundError) {
33539
- return failed2({ message: error2.message, code: "SCHEMA_NOT_FOUND" });
33540
- }
33541
- return failed2({
33542
- message: error2 instanceof Error ? error2.message : "Failed to detect schema source",
33543
- code: "UNKNOWN"
33544
- });
33545
- }
33546
33159
  let loaded;
33547
33160
  try {
33548
33161
  loaded = await loadSchema(options.projectRoot);
@@ -33577,9 +33190,9 @@ async function runLocalVsRemote(options) {
33577
33190
  let plan = null;
33578
33191
  if (hasChanges) {
33579
33192
  try {
33580
- plan = await planSchema(projectId, branchId, loaded.schema);
33193
+ plan = await planManifest(projectId, branchId, { schema: loaded.schema });
33581
33194
  } catch (error2) {
33582
- return failed2(extractApiError2(error2, "Could not read the adaptation plan"));
33195
+ return failed2(extractApiError2(error2, "Could not read the plan"));
33583
33196
  }
33584
33197
  }
33585
33198
  return {
@@ -33587,7 +33200,6 @@ async function runLocalVsRemote(options) {
33587
33200
  mode: "local-vs-remote",
33588
33201
  branchName,
33589
33202
  branchId,
33590
- schemaSourceType: loaded.sourceType,
33591
33203
  schemaSourcePath: loaded.sourcePath,
33592
33204
  hasChanges,
33593
33205
  changes: { ...DEFAULT_CHANGES2, ...status.changes },
@@ -33684,6 +33296,7 @@ var DEFAULT_CHANGES2;
33684
33296
  var init_diff_service = __esm({
33685
33297
  "src/services/diff.service.ts"() {
33686
33298
  init_config();
33299
+ init_manifest();
33687
33300
  init_schema();
33688
33301
  init_manage();
33689
33302
  init_manage_error();
@@ -33735,12 +33348,6 @@ var init_schema_validation = __esm({
33735
33348
  }
33736
33349
  });
33737
33350
 
33738
- // ../../platform/api-contract/dist/chunk-PNSXOOFC.js
33739
- var init_chunk_PNSXOOFC = __esm({
33740
- "../../platform/api-contract/dist/chunk-PNSXOOFC.js"() {
33741
- }
33742
- });
33743
-
33744
33351
  // ../../platform/api-contract/dist/chunk-46347LG2.js
33745
33352
  function defineRoute2(route) {
33746
33353
  if (route.kind === "raw" && route.standardShape === void 0) {
@@ -33831,18 +33438,24 @@ var init_chunk_6JGYNMIT = __esm({
33831
33438
  }
33832
33439
  });
33833
33440
 
33441
+ // ../../platform/api-contract/dist/chunk-PNSXOOFC.js
33442
+ var init_chunk_PNSXOOFC = __esm({
33443
+ "../../platform/api-contract/dist/chunk-PNSXOOFC.js"() {
33444
+ }
33445
+ });
33446
+
33834
33447
  // ../../platform/api-contract/dist/index.js
33835
33448
  function isGitHubIdText(value) {
33836
33449
  return /^[1-9]\d{0,15}$/.test(value) && Number(value) <= Number.MAX_SAFE_INTEGER;
33837
33450
  }
33838
- var HEADER_RETRY_AFTER2, GITHUB_INSTALLATION_EVENTS, GITHUB_REPOSITORY_EVENTS, MODEL_SETTING_RATES, GITHUB_OIDC_AUDIENCE, GITHUB_CONFIRM_PLAN_LABEL, GITHUB_SCHEMA_CHECK_NAME, GITHUB_CI_MAIN_MISSING_RULE;
33451
+ var HEADER_RETRY_AFTER2, GITHUB_INSTALLATION_EVENTS, GITHUB_REPOSITORY_EVENTS, MODEL_SETTING_RATES, GITHUB_OIDC_AUDIENCE, GITHUB_CONFIRM_PLAN_LABEL, GITHUB_PLAN_CHECK_NAME, GITHUB_CI_MAIN_MISSING_RULE;
33839
33452
  var init_dist8 = __esm({
33840
33453
  "../../platform/api-contract/dist/index.js"() {
33841
- init_chunk_PNSXOOFC();
33842
- init_chunk_PAPXNVHQ();
33843
33454
  init_chunk_RR2TKN4K();
33844
33455
  init_chunk_6JGYNMIT();
33845
33456
  init_chunk_OWKTFXBY();
33457
+ init_chunk_PNSXOOFC();
33458
+ init_chunk_PAPXNVHQ();
33846
33459
  init_chunk_BEWKLRXZ();
33847
33460
  init_chunk_46347LG2();
33848
33461
  HEADER_RETRY_AFTER2 = { name: "Retry-After" };
@@ -33866,7 +33479,8 @@ var init_dist8 = __esm({
33866
33479
  "pull_request",
33867
33480
  "deployment_status",
33868
33481
  "release",
33869
- "repository"
33482
+ "repository",
33483
+ "check_suite"
33870
33484
  ];
33871
33485
  [
33872
33486
  ...GITHUB_INSTALLATION_EVENTS,
@@ -33890,7 +33504,7 @@ var init_dist8 = __esm({
33890
33504
  ]);
33891
33505
  GITHUB_OIDC_AUDIENCE = "relyio";
33892
33506
  GITHUB_CONFIRM_PLAN_LABEL = "relyio:confirm-plan";
33893
- GITHUB_SCHEMA_CHECK_NAME = "RelyIO schema";
33507
+ GITHUB_PLAN_CHECK_NAME = "RelyIO plan";
33894
33508
  GITHUB_CI_MAIN_MISSING_RULE = "main-missing";
33895
33509
  }
33896
33510
  });
@@ -34142,65 +33756,6 @@ var init_agent_suggestion = __esm({
34142
33756
  AGENT_SUGGESTION_DISPLAY_HINT = "agentSuggestion";
34143
33757
  }
34144
33758
  });
34145
-
34146
- // src/ai/repl/diff/yaml-outline.ts
34147
- function indentOf(line) {
34148
- let i = 0;
34149
- while (i < line.length && (line[i] === " " || line[i] === " ")) i++;
34150
- return i;
34151
- }
34152
- function scalarOf(written) {
34153
- const text = written?.trim();
34154
- if (!text) return void 0;
34155
- const quote = text[0];
34156
- if (quote === "'" || quote === '"') {
34157
- const end = text.indexOf(quote, 1);
34158
- return end === -1 ? text.slice(1) : text.slice(1, end);
34159
- }
34160
- const comment = text.search(/\s#/);
34161
- return (comment === -1 ? text : text.slice(0, comment)).trim() || void 0;
34162
- }
34163
- function readYamlStep(line) {
34164
- const match = STEP_RE.exec(line.trim());
34165
- if (!match) return void 0;
34166
- const [, dash, singleQuoted, doubleQuoted, bare, written] = match;
34167
- const value = scalarOf(written);
34168
- return {
34169
- key: singleQuoted ?? doubleQuoted ?? bare,
34170
- ...value === void 0 ? {} : { value },
34171
- listItem: dash !== void 0
34172
- };
34173
- }
34174
- function isListItemLine(line) {
34175
- return /^\s*-(\s|$)/.test(line);
34176
- }
34177
- function enclosingSteps(lines, index) {
34178
- const own = lines[index];
34179
- if (own === void 0) return [];
34180
- const steps = [];
34181
- let threshold = indentOf(own);
34182
- let childIsListItem = isListItemLine(own);
34183
- for (let i = index - 1; i >= 0 && (threshold > 0 || childIsListItem); i--) {
34184
- const line = lines[i];
34185
- const trimmed = line.trim();
34186
- if (trimmed === "" || trimmed.startsWith("#")) continue;
34187
- const indent = indentOf(line);
34188
- const step = readYamlStep(line);
34189
- if (step === void 0) continue;
34190
- const opensSequence = indent === threshold && childIsListItem && !step.listItem && step.value === void 0;
34191
- if (indent >= threshold && !opensSequence) continue;
34192
- steps.push(step);
34193
- threshold = indent;
34194
- childIsListItem = step.listItem;
34195
- }
34196
- return steps.reverse();
34197
- }
34198
- var STEP_RE;
34199
- var init_yaml_outline = __esm({
34200
- "src/ai/repl/diff/yaml-outline.ts"() {
34201
- STEP_RE = /^(-\s+)?(?:'([^']+)'|"([^"]+)"|([A-Za-z_$][\w$-]*))\s*:(?:\s+(.*))?$/;
34202
- }
34203
- });
34204
33759
  function buildDiffArtifact(input) {
34205
33760
  const { path: filePath, fileBefore, searchBlock, replaceBlock, fileExisted } = input;
34206
33761
  const action = decideAction({ fileBefore, searchBlock, replaceBlock, fileExisted });
@@ -34226,7 +33781,6 @@ function buildDiffArtifact(input) {
34226
33781
  lines
34227
33782
  });
34228
33783
  }
34229
- if (language === "yaml") placeYamlLines(hunks, fileBefore, fileAfter);
34230
33784
  const truncated = applyGlobalLineCap(hunks, TUNABLES.MAX_TOTAL_LINES);
34231
33785
  return {
34232
33786
  path: filePath,
@@ -34237,17 +33791,6 @@ function buildDiffArtifact(input) {
34237
33791
  ...truncated ? { truncated: true } : {}
34238
33792
  };
34239
33793
  }
34240
- function placeYamlLines(hunks, fileBefore, fileAfter) {
34241
- const before = fileBefore.split("\n");
34242
- const after = fileAfter.split("\n");
34243
- for (const hunk of hunks) {
34244
- for (const line of hunk.lines) {
34245
- if (line.kind === "sep" || line.kind === "truncated") continue;
34246
- const [file, lineNo] = line.kind === "add" ? [after, line.newLineNo] : [before, line.oldLineNo];
34247
- if (lineNo !== void 0) line.enclosing = enclosingSteps(file, lineNo - 1);
34248
- }
34249
- }
34250
- }
34251
33794
  function decideAction(args) {
34252
33795
  if (!args.fileExisted) return "create";
34253
33796
  if (args.replaceBlock === "" && args.searchBlock.trim().length > 0 && args.fileBefore.trim() === args.searchBlock.trim()) {
@@ -34416,7 +33959,7 @@ function deriveAnchor(fileBefore, oldStartLine, language) {
34416
33959
  }
34417
33960
  return void 0;
34418
33961
  }
34419
- function indentOf2(line) {
33962
+ function indentOf(line) {
34420
33963
  let i = 0;
34421
33964
  while (i < line.length && (line[i] === " " || line[i] === " ")) i++;
34422
33965
  return i;
@@ -34428,7 +33971,7 @@ function deriveYamlAnchor(lines, startIdx) {
34428
33971
  const raw = lines[i];
34429
33972
  if (raw.trim().length === 0) continue;
34430
33973
  if (raw.trim().startsWith("#")) continue;
34431
- const ind = indentOf2(raw);
33974
+ const ind = indentOf(raw);
34432
33975
  if (ind >= lastIndent) continue;
34433
33976
  const stripped = raw.slice(ind);
34434
33977
  const match = /^([A-Za-z_][\w-]*)\s*:/.exec(stripped) ?? /^- *([A-Za-z_][\w-]*)\s*:/.exec(stripped);
@@ -34469,7 +34012,6 @@ function detectLanguage(filePath) {
34469
34012
  var TUNABLES, EXT_TO_LANG;
34470
34013
  var init_build_artifact = __esm({
34471
34014
  "src/ai/repl/diff/build-artifact.ts"() {
34472
- init_yaml_outline();
34473
34015
  TUNABLES = {
34474
34016
  /** Lines of unchanged context kept around a change in symmetric diffs. */
34475
34017
  CONTEXT_LINES: 2,
@@ -34552,7 +34094,7 @@ function summarizePreview(preview2) {
34552
34094
  });
34553
34095
  const { added, modified, deleted } = countChanges(preview2.changes);
34554
34096
  const totals = { added, modified, removed: deleted };
34555
- const schemaSource = preview2.schemaSourceType === "typescript" ? `TypeScript (${preview2.schemaSourcePath.split("/").slice(-2).join("/")})` : `YAML (${preview2.schemaSourcePath.length} files)`;
34097
+ const schemaSource = `TypeScript (${preview2.schemaSourcePath.split("/").slice(-2).join("/")})`;
34556
34098
  return {
34557
34099
  branchName: preview2.branchName,
34558
34100
  branchId: preview2.branchId,
@@ -35688,27 +35230,13 @@ var init_context_provider = __esm({
35688
35230
  return process.cwd();
35689
35231
  }
35690
35232
  async buildFileManifest(projectRoot) {
35691
- const schemaSourceType = await this.detectSchemaSourceType(projectRoot);
35692
- const schemaFiles = await this.discoverSchemaFiles(projectRoot, schemaSourceType);
35693
- return { schemaSourceType, schemaFiles, projectRoot };
35233
+ const schemaFiles = await this.discoverSchemaFiles(projectRoot);
35234
+ return { schemaSourceType: "typescript", schemaFiles, projectRoot };
35694
35235
  }
35695
- async detectSchemaSourceType(projectRoot) {
35696
- const tsFiles = await glob("**/relyio/**/*.ts", {
35697
- cwd: projectRoot,
35698
- ignore: ["node_modules/**"]
35699
- });
35700
- if (tsFiles.length > 0) return "typescript";
35701
- const yamlFiles = await glob("**/relyio/**/*.{yaml,yml}", {
35702
- cwd: projectRoot,
35703
- ignore: ["node_modules/**"]
35704
- });
35705
- if (yamlFiles.length > 0) return "yaml";
35706
- return "typescript";
35707
- }
35708
- async discoverSchemaFiles(projectRoot, sourceType) {
35236
+ /** The schema is TypeScript only (ADR 0021): the `.ts` files under `relyio/`. */
35237
+ async discoverSchemaFiles(projectRoot) {
35709
35238
  const { stat: stat2 } = await import('fs/promises');
35710
- const pattern = sourceType === "typescript" ? "**/relyio/**/*.ts" : "**/relyio/**/*.{yaml,yml}";
35711
- const files = await glob(pattern, {
35239
+ const files = await glob("**/relyio/**/*.ts", {
35712
35240
  cwd: projectRoot,
35713
35241
  ignore: ["node_modules/**", "dist/**", ".git/**"]
35714
35242
  });
@@ -35731,7 +35259,7 @@ var init_context_provider = __esm({
35731
35259
  if (!dir) return void 0;
35732
35260
  const fileName = parts.at(-1);
35733
35261
  if (!fileName) return void 0;
35734
- const name = fileName.replace(/\.(ts|yaml|yml)$/, "");
35262
+ const name = fileName.replace(/\.ts$/, "");
35735
35263
  return name === "index" ? void 0 : name;
35736
35264
  }
35737
35265
  };
@@ -35983,11 +35511,9 @@ async function runLocalValidation(projectRoot) {
35983
35511
  try {
35984
35512
  const result = await validateLocalSchema(projectRoot);
35985
35513
  const durationMs = Date.now() - start;
35986
- const sourcePath = Array.isArray(result.sourcePath) ? result.sourcePath.map((p) => relativize(p, projectRoot)) : relativize(result.sourcePath, projectRoot);
35987
35514
  return {
35988
35515
  success: result.errors.length === 0,
35989
- sourceType: result.sourceType,
35990
- sourcePath,
35516
+ sourcePath: relativize(result.sourcePath, projectRoot),
35991
35517
  durationMs,
35992
35518
  errors: result.errors.map((e) => ({
35993
35519
  file: relativize(e.file, projectRoot),
@@ -36006,9 +35532,13 @@ async function runLocalValidation(projectRoot) {
36006
35532
  durationMs,
36007
35533
  errors: [],
36008
35534
  warnings: [],
36009
- fatal: {
35535
+ fatal: error2.yamlFiles.length > 0 ? {
35536
+ // The loader's one refusal: TypeScript is the only schema source (REL-3711)
35537
+ error: error2.message,
35538
+ hint: "Write the schema in relyio/schema.ts with the define* functions from @relyio/sdk/schema."
35539
+ } : {
36010
35540
  error: "No schema found in this project.",
36011
- hint: "Make sure relyio.config.{ts,js} or a relyio/ directory with YAML schema files exists at the project root."
35541
+ hint: "Make sure relyio/schema.ts or relyio/schema/index.ts exists at the project root."
36012
35542
  }
36013
35543
  };
36014
35544
  }
@@ -36055,7 +35585,6 @@ var init_run_validation_handler = __esm({
36055
35585
  }
36056
35586
  return {
36057
35587
  success: result.success,
36058
- sourceType: result.sourceType,
36059
35588
  sourcePath: result.sourcePath,
36060
35589
  durationMs: result.durationMs,
36061
35590
  errors: result.errors,
@@ -36138,7 +35667,6 @@ var init_local_diff_handler = __esm({
36138
35667
  mode: "local-vs-remote",
36139
35668
  branchName: result.branchName,
36140
35669
  branchId: result.branchId,
36141
- schemaSourceType: result.schemaSourceType,
36142
35670
  hasChanges: result.hasChanges,
36143
35671
  summary,
36144
35672
  ...result.hasChanges ? {
@@ -36255,7 +35783,7 @@ var init_local_deploy_handler = __esm({
36255
35783
  "src/ai/handlers/local-deploy.handler.ts"() {
36256
35784
  init_deploy_service();
36257
35785
  init_change_buckets();
36258
- init_adaptation_plan();
35786
+ init_deploy_plan();
36259
35787
  DeployPreviewCache = class {
36260
35788
  store = /* @__PURE__ */ new Map();
36261
35789
  set(toolCallId, value) {
@@ -36321,10 +35849,10 @@ var init_local_deploy_handler = __esm({
36321
35849
  success: false,
36322
35850
  status: "plan-required",
36323
35851
  branchName: result.preview.branchName,
36324
- message: `Not deployed: this deploy ${summarizeAdaptationPlan(plan)}. Show the person this plan as it is. Do not retry the deploy and do not accept the plan yourself: they apply it by running \`relyio deploy\` and answering yes, or \`relyio deploy --accept-plan ${plan.planId}\`.`,
36325
- plan: stripAnsi2(formatAdaptationPlan(plan)),
35852
+ message: `Not deployed: this deploy ${summarizeDeployPlan(plan)}. Show the person this plan as it is. Do not retry the deploy and do not accept the plan yourself: they apply it by running \`relyio deploy\` and answering yes, or \`relyio deploy --accept-plan ${plan.planId}\`.`,
35853
+ plan: stripAnsi2(formatDeployPlan(plan)),
36326
35854
  planId: plan.planId,
36327
- ...result.blockage.kind === "schema-plan-stale" ? { stale: true } : {}
35855
+ ...result.blockage.kind === "manifest-plan-stale" ? { stale: true } : {}
36328
35856
  };
36329
35857
  }
36330
35858
  return {
@@ -36515,9 +36043,9 @@ var init_runtime = __esm({
36515
36043
 
36516
36044
  // src/ai/core/tool-failure.ts
36517
36045
  function toolFailureOf(result) {
36518
- if (!isRecord9(result) || result.success === true) return void 0;
36046
+ if (!isRecord8(result) || result.success === true) return void 0;
36519
36047
  const { error: error2 } = result;
36520
- if (isRecord9(error2) && typeof error2.code === "string" && Array.isArray(error2.messages)) {
36048
+ if (isRecord8(error2) && typeof error2.code === "string" && Array.isArray(error2.messages)) {
36521
36049
  const messages = error2.messages.filter((line) => typeof line === "string");
36522
36050
  return { code: error2.code, message: messages.join(" ") };
36523
36051
  }
@@ -36529,10 +36057,10 @@ function describeToolFailure(failure) {
36529
36057
  if (failure.code === void 0) return failure.message;
36530
36058
  return failure.message ? `${failure.code}: ${failure.message}` : failure.code;
36531
36059
  }
36532
- var isRecord9;
36060
+ var isRecord8;
36533
36061
  var init_tool_failure = __esm({
36534
36062
  "src/ai/core/tool-failure.ts"() {
36535
- isRecord9 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
36063
+ isRecord8 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
36536
36064
  }
36537
36065
  });
36538
36066
  function initialSessionState(options) {
@@ -37315,7 +36843,6 @@ function buildStartupInfo(context, fileManifest, mode) {
37315
36843
  projectName: context.projectName,
37316
36844
  branchName: context.branchName,
37317
36845
  datasetName: context.datasetName,
37318
- schemaSourceType: fileManifest.schemaSourceType,
37319
36846
  schemaFileCount: fileManifest.schemaFiles.length,
37320
36847
  mode
37321
36848
  };
@@ -37328,7 +36855,7 @@ function Banner() {
37328
36855
  const { runtime, state } = useRuntime();
37329
36856
  const dev = useDevCockpit();
37330
36857
  const info2 = buildStartupInfo(runtime.context, runtime.fileManifest, state.permissionMode);
37331
- const schemaLabel = info2.schemaSourceType === "typescript" ? "TypeScript" : "YAML";
36858
+ const schemaLabel = "TypeScript";
37332
36859
  const schemaSuffix = `${info2.schemaFileCount} file${info2.schemaFileCount === 1 ? "" : "s"}`;
37333
36860
  const project = scopeDisplay(info2.projectName, runtime.context.projectId);
37334
36861
  const branch = scopeDisplay(info2.branchName, runtime.context.branchId);
@@ -37441,7 +36968,7 @@ var init_banner = __esm({
37441
36968
  init_dev_cockpit_context();
37442
36969
  init_dev_cockpit_format();
37443
36970
  init_startup_info();
37444
- CLI_VERSION2 = "0.11.0" ;
36971
+ CLI_VERSION2 = "0.12.0" ;
37445
36972
  BRAND_GLYPH = "\u25B6";
37446
36973
  BRAND_NAME = "RelyIO";
37447
36974
  LABEL_WIDTH = 9;
@@ -40316,157 +39843,6 @@ var init_suggest_agent_card = __esm({
40316
39843
  init_picker_card();
40317
39844
  }
40318
39845
  });
40319
-
40320
- // src/ai/repl/diff/semantic-summary.ts
40321
- function buildSemanticSummary(artifact) {
40322
- if (!artifact.language) return [];
40323
- if (artifact.language !== "yaml") return [];
40324
- return summariseYamlSchemaDiff(artifact);
40325
- }
40326
- function isSection3(key) {
40327
- return Object.hasOwn(DEFINITION_SECTIONS, key);
40328
- }
40329
- function scopeOf2(steps) {
40330
- return steps.map((step) => step.listItem ? step.value ?? step.key : step.key).join(".");
40331
- }
40332
- function placeItem(item, enclosing) {
40333
- if (!item.listItem || item.value === void 0) return void 0;
40334
- const [section, ...within] = enclosing;
40335
- if (!section || section.listItem || !isSection3(section.key)) return void 0;
40336
- const items = SECTION_ITEMS[section.key];
40337
- const listedUnder = items.listedUnder === void 0 ? [] : [items.listedUnder];
40338
- const isSectionItem = within.length === listedUnder.length && within.every((step, i) => !step.listItem && step.key === listedUnder[i]);
40339
- if (isSectionItem) {
40340
- return item.key === items.label ? { kind: items.noun, name: item.value } : void 0;
40341
- }
40342
- const parent = within.at(-1);
40343
- if (parent && !parent.listItem && parent.key === "fields" && item.key === "id") {
40344
- return { kind: "field", name: item.value, scope: scopeOf2(enclosing.slice(0, -1)) };
40345
- }
40346
- return void 0;
40347
- }
40348
- function isTextLine(line) {
40349
- return line.kind === "add" || line.kind === "remove" || line.kind === "context";
40350
- }
40351
- function summariseYamlSchemaDiff(artifact) {
40352
- const bullets = [];
40353
- for (const hunk of artifact.hunks) {
40354
- const added = collectItems(hunk.lines, "add");
40355
- const removed = collectItems(hunk.lines, "remove");
40356
- const removedByKey = new Map(removed.map((item) => [itemKey(item), item]));
40357
- for (const item of added) {
40358
- const before = removedByKey.get(itemKey(item));
40359
- if (before) {
40360
- removedByKey.delete(itemKey(item));
40361
- if (item.type && before.type !== item.type) {
40362
- bullets.push(bullet("modified", item, `type: ${item.type}`));
40363
- }
40364
- continue;
40365
- }
40366
- bullets.push(bullet("added", item, item.type ? `type: ${item.type}` : void 0));
40367
- }
40368
- for (const item of removedByKey.values()) bullets.push(bullet("removed", item));
40369
- if (added.length === 0 && removed.length === 0) {
40370
- bullets.push(...detectPropertyChanges(hunk.lines));
40371
- }
40372
- }
40373
- return dedupe(bullets);
40374
- }
40375
- function itemKey(item) {
40376
- return `${item.kind}::${item.scope ?? ""}::${item.name}`;
40377
- }
40378
- function bullet(action, item, detail) {
40379
- return {
40380
- action,
40381
- entityKind: item.kind,
40382
- entityName: item.name,
40383
- ...item.scope === void 0 ? {} : { scope: item.scope },
40384
- ...detail === void 0 ? {} : { detail }
40385
- };
40386
- }
40387
- function collectItems(lines, kind) {
40388
- const items = [];
40389
- for (let i = 0; i < lines.length; i++) {
40390
- const line = lines[i];
40391
- if (line.kind !== kind || !isTextLine(line)) continue;
40392
- const step = readYamlStep(line.text);
40393
- const placed = step && line.enclosing ? placeItem(step, line.enclosing) : void 0;
40394
- if (!placed) continue;
40395
- let type;
40396
- if (placed.kind === "field") {
40397
- for (let j = i + 1; j < Math.min(i + 8, lines.length); j++) {
40398
- const next = lines[j];
40399
- if (next.kind !== kind || !isTextLine(next)) break;
40400
- const match = FIELD_TYPE_RE.exec(next.text);
40401
- if (match) {
40402
- type = match[1];
40403
- break;
40404
- }
40405
- }
40406
- }
40407
- items.push({ ...placed, ...type === void 0 ? {} : { type } });
40408
- }
40409
- return items;
40410
- }
40411
- function detectPropertyChanges(lines) {
40412
- const bullets = [];
40413
- for (let i = 0; i < lines.length - 1; i++) {
40414
- const a = lines[i];
40415
- const b = lines[i + 1];
40416
- if (a.kind !== "remove" || b.kind !== "add" || !isTextLine(a) || !isTextLine(b)) continue;
40417
- const removed = readYamlStep(a.text);
40418
- const added = readYamlStep(b.text);
40419
- if (!removed || !added || removed.listItem || added.listItem) continue;
40420
- if (removed.key !== added.key) continue;
40421
- if (added.value === void 0 || removed.value === added.value) continue;
40422
- const enclosing = b.enclosing ?? [];
40423
- let at = enclosing.length - 1;
40424
- while (at >= 0 && !enclosing[at].listItem) at--;
40425
- if (at === -1) continue;
40426
- const item = placeItem(enclosing[at], enclosing.slice(0, at));
40427
- if (!item) continue;
40428
- bullets.push(bullet("modified", item, `${added.key}: ${added.value}`));
40429
- }
40430
- return bullets;
40431
- }
40432
- function dedupe(bullets) {
40433
- const seen = /* @__PURE__ */ new Set();
40434
- const result = [];
40435
- for (const b of bullets) {
40436
- const key = `${b.action}::${b.entityKind}::${b.entityName}::${b.scope ?? ""}::${b.detail ?? ""}`;
40437
- if (seen.has(key)) continue;
40438
- seen.add(key);
40439
- result.push(b);
40440
- }
40441
- return result;
40442
- }
40443
- function formatBullet(bullet2) {
40444
- const verb = bullet2.action === "added" ? "Added" : bullet2.action === "removed" ? "Removed" : bullet2.action === "modified" ? "Modified" : "Renamed";
40445
- const base = `${verb} ${bullet2.entityKind} \`${bullet2.entityName}\``;
40446
- const scope = bullet2.scope ? ` in ${bullet2.scope}` : "";
40447
- const detail = bullet2.detail ? ` (${bullet2.detail})` : "";
40448
- return base + scope + detail;
40449
- }
40450
- var SECTION_ITEMS, FIELD_TYPE_RE;
40451
- var init_semantic_summary = __esm({
40452
- "src/ai/repl/diff/semantic-summary.ts"() {
40453
- init_dist3();
40454
- init_dist4();
40455
- init_yaml_outline();
40456
- SECTION_ITEMS = {
40457
- locales: { noun: "locale", label: LIST_ITEM_KEYS.locales[0] },
40458
- roles: { noun: "role", label: LIST_ITEM_KEYS.roles[0] },
40459
- workflow: { noun: "workflow stage", label: "id", listedUnder: "stages" },
40460
- contentTypes: { noun: "content type", label: "id" },
40461
- singletonContentTypes: { noun: "singleton type", label: "id" },
40462
- assetTypes: { noun: "asset type", label: "id" },
40463
- queries: { noun: "query", label: "id" },
40464
- settingsGroups: { noun: "settings group", label: "id" },
40465
- views: { noun: "view", label: LIST_ITEM_KEYS.views[0] }
40466
- };
40467
- FIELD_TYPE_RE = /^\s*type:\s*['"]?([A-Za-z0-9_-]+)['"]?/;
40468
- }
40469
- });
40470
39846
  function DiffCard({
40471
39847
  artifact,
40472
39848
  collapsed = false,
@@ -40475,12 +39851,10 @@ function DiffCard({
40475
39851
  searchQuery
40476
39852
  }) {
40477
39853
  const hunks = collapsed ? collapseHunks(artifact.hunks) : artifact.hunks;
40478
- const semanticBullets = showHeader ? buildSemanticSummary(artifact) : [];
40479
39854
  const body = /* @__PURE__ */ jsxs(Fragment, { children: [
40480
39855
  showHeader && artifact.reasoning && /* @__PURE__ */ jsx(WhyPanel, { reasoning: artifact.reasoning }),
40481
39856
  showHeader && /* @__PURE__ */ jsx(DiffHeader, { artifact }),
40482
39857
  /* @__PURE__ */ jsx(TrustStrip, { artifact }),
40483
- semanticBullets.length > 0 && /* @__PURE__ */ jsx(SemanticPanel, { bullets: semanticBullets }),
40484
39858
  hunks.map((hunk, i) => /* @__PURE__ */ jsx(HunkView, { hunk, language: artifact.language, searchQuery }, i)),
40485
39859
  artifact.truncated && /* @__PURE__ */ jsx(Box, { marginTop: 1, children: /* @__PURE__ */ jsx(Text, { dimColor: true, italic: true, children: "\u2026 diff truncated to fit the prompt" }) })
40486
39860
  ] });
@@ -40553,27 +39927,6 @@ function TrustStrip({ artifact }) {
40553
39927
  " \xB7 review carefully"
40554
39928
  ] }) });
40555
39929
  }
40556
- function SemanticPanel({ bullets }) {
40557
- const visible = bullets.slice(0, 6);
40558
- const overflow = bullets.length - visible.length;
40559
- return /* @__PURE__ */ jsxs(Box, { flexDirection: "column", marginTop: 1, children: [
40560
- /* @__PURE__ */ jsx(Text, { dimColor: true, bold: true, children: "Schema changes" }),
40561
- visible.map((bullet2, i) => /* @__PURE__ */ jsxs(Text, { children: [
40562
- /* @__PURE__ */ jsxs(Text, { color: SEMANTIC_COLOR[bullet2.action], children: [
40563
- " ",
40564
- SEMANTIC_GLYPH[bullet2.action],
40565
- " "
40566
- ] }),
40567
- /* @__PURE__ */ jsx(Text, { children: formatBullet(bullet2) })
40568
- ] }, i)),
40569
- overflow > 0 && /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
40570
- " ",
40571
- "\u2026and ",
40572
- overflow,
40573
- " more"
40574
- ] })
40575
- ] });
40576
- }
40577
39930
  function DiffHeader({ artifact }) {
40578
39931
  return /* @__PURE__ */ jsx(Box, { flexDirection: "column", children: /* @__PURE__ */ jsxs(Text, { children: [
40579
39932
  /* @__PURE__ */ jsx(Text, { dimColor: true, children: artifact.path }),
@@ -40733,12 +40086,11 @@ function SpanLine({ spans, kind }) {
40733
40086
  return /* @__PURE__ */ jsx(Text, { color: baseColor, inverse: true, children: span.text }, i);
40734
40087
  }) });
40735
40088
  }
40736
- var ACTION_LABEL2, ACTION_COLOR2, MAX_INLINE_DIFF_LINES, COLLAPSED_HEAD_LINES, COLLAPSED_TAIL_LINES, WHY_PANEL_MAX_CHARS, SEMANTIC_GLYPH, SEMANTIC_COLOR;
40089
+ var ACTION_LABEL2, ACTION_COLOR2, MAX_INLINE_DIFF_LINES, COLLAPSED_HEAD_LINES, COLLAPSED_TAIL_LINES, WHY_PANEL_MAX_CHARS;
40737
40090
  var init_diff_card = __esm({
40738
40091
  "src/ai/repl/diff/diff-card.tsx"() {
40739
40092
  init_syntax_highlight();
40740
40093
  init_card();
40741
- init_semantic_summary();
40742
40094
  ACTION_LABEL2 = {
40743
40095
  create: "create",
40744
40096
  modify: "modify",
@@ -40753,18 +40105,6 @@ var init_diff_card = __esm({
40753
40105
  COLLAPSED_HEAD_LINES = 24;
40754
40106
  COLLAPSED_TAIL_LINES = 10;
40755
40107
  WHY_PANEL_MAX_CHARS = 400;
40756
- SEMANTIC_GLYPH = {
40757
- added: "+",
40758
- removed: "\u2212",
40759
- modified: "~",
40760
- renamed: "\u21D2"
40761
- };
40762
- SEMANTIC_COLOR = {
40763
- added: "green",
40764
- removed: "red",
40765
- modified: "yellow",
40766
- renamed: "cyan"
40767
- };
40768
40108
  }
40769
40109
  });
40770
40110
  function ConfirmationPrompt({
@@ -42459,13 +41799,13 @@ function executeSlashCommand(command, args, ctx) {
42459
41799
  return;
42460
41800
  }
42461
41801
  let applied = 0;
42462
- let failed3 = 0;
41802
+ let failed4 = 0;
42463
41803
  for (const parent of pendingParents) {
42464
41804
  try {
42465
41805
  await client.applyGroup(projectId, parent.id);
42466
41806
  applied += parent.children.filter((c) => c.status === "pending").length;
42467
41807
  } catch {
42468
- failed3 += parent.children.filter((c) => c.status === "pending").length;
41808
+ failed4 += parent.children.filter((c) => c.status === "pending").length;
42469
41809
  }
42470
41810
  }
42471
41811
  if (pendingOrphans.length > 0) {
@@ -42476,7 +41816,7 @@ function executeSlashCommand(command, args, ctx) {
42476
41816
  );
42477
41817
  applied += pendingOrphans.length;
42478
41818
  } catch {
42479
- failed3 += pendingOrphans.length;
41819
+ failed4 += pendingOrphans.length;
42480
41820
  }
42481
41821
  }
42482
41822
  try {
@@ -42497,7 +41837,7 @@ function executeSlashCommand(command, args, ctx) {
42497
41837
  ctx.dispatch({
42498
41838
  type: "SYSTEM_MESSAGE_APPENDED",
42499
41839
  label: "/commit",
42500
- text: failed3 === 0 ? `Applied ${applied} proposal${applied === 1 ? "" : "s"}. Reload your app to see them.` : `Applied ${applied} proposal${applied === 1 ? "" : "s"}; ${failed3} failed. Run /proposals for details.`
41840
+ text: failed4 === 0 ? `Applied ${applied} proposal${applied === 1 ? "" : "s"}. Reload your app to see them.` : `Applied ${applied} proposal${applied === 1 ? "" : "s"}; ${failed4} failed. Run /proposals for details.`
42501
41841
  });
42502
41842
  } catch (error2) {
42503
41843
  ctx.dispatch({
@@ -42695,8 +42035,8 @@ function buildDiffSystemMessage(result) {
42695
42035
  }
42696
42036
  }
42697
42037
  }
42698
- if (result.mode === "local-vs-remote" && result.plan && planHasContent(result.plan)) {
42699
- lines.push("", stripAnsi2(formatAdaptationPlan(result.plan)));
42038
+ if (result.mode === "local-vs-remote" && result.plan && deployPlanHasContent(result.plan)) {
42039
+ lines.push("", stripAnsi2(formatDeployPlan(result.plan)));
42700
42040
  }
42701
42041
  return lines.join("\n");
42702
42042
  }
@@ -42722,7 +42062,7 @@ function buildDeploySystemMessage(result) {
42722
42062
  return [
42723
42063
  `[Not deployed to ${result.preview.branchName}: this deploy changes stored content]`,
42724
42064
  "",
42725
- stripAnsi2(formatAdaptationPlan(plan)),
42065
+ stripAnsi2(formatDeployPlan(plan)),
42726
42066
  "",
42727
42067
  `Show the person this plan. Do not retry and do not accept it: they apply it with \`relyio deploy\` (answering yes) or \`relyio deploy --accept-plan ${plan.planId}\`.`
42728
42068
  ].join("\n");
@@ -42778,12 +42118,11 @@ function formatContextInfo(ctx) {
42778
42118
  const sessionLabel = state.sessionName ? `${state.sessionName} (${state.sessionId.slice(-6)})` : state.sessionId ? state.sessionId.slice(-6) : "\u2014";
42779
42119
  const turns = state.messages.filter((m) => m.role === "assistant").length;
42780
42120
  const schemaFiles = runtime.fileManifest.schemaFiles.length;
42781
- const schemaType = runtime.fileManifest.schemaSourceType;
42782
42121
  return [
42783
42122
  `Project ${projectCell}`,
42784
42123
  `Branch ${branchCell}`,
42785
42124
  `Dataset ${datasetCell}`,
42786
- `Schema ${schemaType} \xB7 ${schemaFiles} file${schemaFiles === 1 ? "" : "s"}`,
42125
+ `Schema TypeScript \xB7 ${schemaFiles} file${schemaFiles === 1 ? "" : "s"}`,
42787
42126
  `Agent ${agent}`,
42788
42127
  `Mode ${state.permissionMode}`,
42789
42128
  `Session ${sessionLabel}`,
@@ -43032,7 +42371,7 @@ var init_executor = __esm({
43032
42371
  init_compaction();
43033
42372
  init_local_validation();
43034
42373
  init_change_buckets();
43035
- init_adaptation_plan();
42374
+ init_deploy_plan();
43036
42375
  init_deploy_service();
43037
42376
  init_diff_service();
43038
42377
  init_session_history();
@@ -43714,7 +43053,7 @@ function patchRuntimeContext(runtime, resolved) {
43714
43053
  async function applyAllPending(projectId, conversationId) {
43715
43054
  const client = getProposalsClient();
43716
43055
  let applied = 0;
43717
- let failed3 = 0;
43056
+ let failed4 = 0;
43718
43057
  try {
43719
43058
  const summary = await client.getSummary(projectId, conversationId);
43720
43059
  const rows = Array.isArray(summary?.proposals) ? summary.proposals : [];
@@ -43725,7 +43064,7 @@ async function applyAllPending(projectId, conversationId) {
43725
43064
  await client.applyGroup(projectId, parent.id);
43726
43065
  applied += parent.children.filter((c) => c.status === "pending").length;
43727
43066
  } catch {
43728
- failed3 += parent.children.filter((c) => c.status === "pending").length;
43067
+ failed4 += parent.children.filter((c) => c.status === "pending").length;
43729
43068
  }
43730
43069
  }
43731
43070
  if (pendingOrphans.length > 0) {
@@ -43736,12 +43075,12 @@ async function applyAllPending(projectId, conversationId) {
43736
43075
  );
43737
43076
  applied += pendingOrphans.length;
43738
43077
  } catch {
43739
- failed3 += pendingOrphans.length;
43078
+ failed4 += pendingOrphans.length;
43740
43079
  }
43741
43080
  }
43742
43081
  } catch {
43743
43082
  }
43744
- return { applied, failed: failed3 };
43083
+ return { applied, failed: failed4 };
43745
43084
  }
43746
43085
  async function refreshProposals(projectId, conversationId) {
43747
43086
  try {
@@ -43852,18 +43191,18 @@ init_exit_codes();
43852
43191
  // src/presenter/schema-changes.ts
43853
43192
  init_change_buckets();
43854
43193
  var style = {
43855
- primary: chalk10.cyan,
43856
- secondary: chalk10.blue,
43857
- success: chalk10.green,
43858
- warning: chalk10.yellow,
43859
- error: chalk10.red,
43860
- muted: chalk10.gray,
43861
- accent: chalk10.magenta,
43862
- dim: chalk10.dim,
43863
- bold: chalk10.bold,
43864
- heading: chalk10.bold.white,
43194
+ primary: chalk12.cyan,
43195
+ secondary: chalk12.blue,
43196
+ success: chalk12.green,
43197
+ warning: chalk12.yellow,
43198
+ error: chalk12.red,
43199
+ muted: chalk12.gray,
43200
+ accent: chalk12.magenta,
43201
+ dim: chalk12.dim,
43202
+ bold: chalk12.bold,
43203
+ heading: chalk12.bold.white,
43865
43204
  /** A command the reader can type, e.g. `relyio deploy`. */
43866
- command: (command) => chalk10.cyan(`$ ${command}`)
43205
+ command: (command) => chalk12.cyan(`$ ${command}`)
43867
43206
  };
43868
43207
  var icons = {
43869
43208
  success: "\u2713",
@@ -44522,6 +43861,7 @@ init_config();
44522
43861
  init_manage();
44523
43862
 
44524
43863
  // src/utils/templates-dir.ts
43864
+ init_dist4();
44525
43865
  init_environment();
44526
43866
  var __dirname = path5.dirname(fileURLToPath(import.meta.url));
44527
43867
  function getTemplatesDir() {
@@ -44547,7 +43887,7 @@ Set RELYIO_CLI_TEMPLATES_DIR to point at the templates folder, or reinstall the
44547
43887
  function schemaTemplateNames(templatesDir) {
44548
43888
  return readdirSync(templatesDir).filter((item) => {
44549
43889
  const fullPath = path5.join(templatesDir, item);
44550
- return statSync(fullPath).isDirectory() && item !== "node_modules" && !item.startsWith(".") && existsSync(path5.join(fullPath, "schemas"));
43890
+ return statSync(fullPath).isDirectory() && item !== "node_modules" && !item.startsWith(".") && TS_SCHEMA_PATHS.some((entry) => existsSync(path5.join(fullPath, entry)));
44551
43891
  }).sort();
44552
43892
  }
44553
43893
  function copySchemaTemplate(template, relyioDir) {
@@ -45174,6 +44514,7 @@ async function handleInit(options) {
45174
44514
  try {
45175
44515
  await tasks.run(context);
45176
44516
  out.success("RelyIO project initialized successfully");
44517
+ out.info("Your schema is relyio/schema.ts. It imports @relyio/sdk: add it to your project.");
45177
44518
  } catch (error2) {
45178
44519
  throw fail(`Failed to initialize project: ${error2.message}`, "INIT_FAILED");
45179
44520
  }
@@ -45481,7 +44822,6 @@ function createStatusJsonOutput(params) {
45481
44822
  const {
45482
44823
  branchName,
45483
44824
  branchId,
45484
- schemaSourceType,
45485
44825
  schemaSourcePath,
45486
44826
  gitCommitSha,
45487
44827
  hasChanges,
@@ -45499,7 +44839,6 @@ function createStatusJsonOutput(params) {
45499
44839
  id: branchId
45500
44840
  },
45501
44841
  schema: {
45502
- source: schemaSourceType,
45503
44842
  path: schemaSourcePath
45504
44843
  },
45505
44844
  ...gitCommitSha && { git: { commitSha: gitCommitSha } },
@@ -45569,7 +44908,6 @@ function createDiffJsonOutput(params) {
45569
44908
  const {
45570
44909
  branchName,
45571
44910
  branchId,
45572
- schemaSourceType,
45573
44911
  schemaSourcePath,
45574
44912
  hasChanges,
45575
44913
  changes,
@@ -45589,7 +44927,6 @@ function createDiffJsonOutput(params) {
45589
44927
  id: branchId
45590
44928
  },
45591
44929
  schema: {
45592
- source: schemaSourceType,
45593
44930
  path: schemaSourcePath
45594
44931
  },
45595
44932
  diff: projectChangeBuckets(changes, (bucket, key) => ({
@@ -45620,7 +44957,6 @@ function createValidateJsonOutput(params) {
45620
44957
  };
45621
44958
  return {
45622
44959
  success: failure === void 0,
45623
- sourceType: check.sourceType,
45624
44960
  sourcePath: check.sourcePath,
45625
44961
  durationMs: Math.round(durationMs),
45626
44962
  errors: check.errors,
@@ -45638,6 +44974,8 @@ init_config();
45638
44974
  // src/commands/promote.ts
45639
44975
  init_manage();
45640
44976
  init_manage_error();
44977
+ init_manifest();
44978
+ init_schema();
45641
44979
 
45642
44980
  // src/api/sandbox.ts
45643
44981
  init_client2();
@@ -45789,10 +45127,13 @@ ${DEV_CONTEXT_FILE}
45789
45127
  }
45790
45128
 
45791
45129
  // src/commands/promote.ts
45792
- init_adaptation_plan();
45130
+ init_deploy_plan();
45793
45131
  init_git();
45794
45132
 
45795
45133
  // src/utils/plan-acceptance.ts
45134
+ function isStale(blockage) {
45135
+ return "confirmedPlanId" in blockage;
45136
+ }
45796
45137
  var PLAN_ID_PATTERN = /^[0-9a-f]{64}$/;
45797
45138
  var DEPLOY_COMMAND = {
45798
45139
  verb: "deploy",
@@ -45806,17 +45147,17 @@ var PROMOTE_COMMAND = {
45806
45147
  };
45807
45148
  function acceptPlanOptionError(value) {
45808
45149
  if (value === void 0 || PLAN_ID_PATTERN.test(value)) return void 0;
45809
- return `--accept-plan takes a plan id (64 lowercase hex digits), as \`relyio diff\` and a refused deploy or promote print it; got "${value}".`;
45150
+ return `--accept-plan takes a plan id (64 lowercase hex digits), as a refused deploy or promote prints it, and \`relyio plan\` for a deploy; got "${value}".`;
45810
45151
  }
45811
45152
  function acceptPlanFlag(plan) {
45812
45153
  return `--accept-plan ${plan.planId}`;
45813
45154
  }
45814
45155
  function planBlockageHeadline(blockage, command) {
45815
- return blockage.kind === "schema-plan-stale" ? "The plan changed since it was read: the branch\u2019s active schema moved. This is the plan now." : `This ${command.verb} changes stored content. Read the plan before it is applied.`;
45156
+ return isStale(blockage) ? "The plan changed since it was read: the branch\u2019s active schema moved. This is the plan now." : `This ${command.verb} changes stored content. Read the plan before it is applied.`;
45816
45157
  }
45817
45158
  function planNotAcceptedMessage(blockage, command) {
45818
45159
  const accept = acceptPlanFlag(blockage.plan);
45819
- return blockage.kind === "schema-plan-stale" ? `The plan ${blockage.confirmedPlanId} is not this ${command.verb}'s plan any more: the branch's active schema moved, or the schema differs. Nothing was ${command.done}. Read the plan now in effect; to apply it, ${command.verb} again with ${accept}.` : `This ${command.verb} changes stored content, and ${command.unattended}. Nothing was ${command.done}. Read the plan; to apply it, ${command.verb} again with ${accept}.`;
45160
+ return isStale(blockage) ? `The plan ${blockage.confirmedPlanId} is not this ${command.verb}'s plan any more: the branch's active schema moved, or the schema differs. Nothing was ${command.done}. Read the plan now in effect; to apply it, ${command.verb} again with ${accept}.` : `This ${command.verb} changes stored content, and ${command.unattended}. Nothing was ${command.done}. Read the plan; to apply it, ${command.verb} again with ${accept}.`;
45820
45161
  }
45821
45162
  var REQUIRED_VALUE = {
45822
45163
  leaves: "would leave required values missing",
@@ -45844,6 +45185,28 @@ function planRefusedMessage(plan, command) {
45844
45185
  return `${verb} refused: ${said.join(", and ")}. ${advice.charAt(0).toUpperCase()}${advice.slice(1)}.`;
45845
45186
  }
45846
45187
 
45188
+ // src/utils/queued-adaptation.ts
45189
+ function datasetLabel(dataset) {
45190
+ return dataset.datasetName === null ? dataset.datasetId : `${dataset.datasetName} (${dataset.datasetId})`;
45191
+ }
45192
+ function displayQueuedAdaptation(adaptation, followUp) {
45193
+ console.log();
45194
+ if (adaptation.queueFailure !== void 0) {
45195
+ out.warning(
45196
+ "The schema deployed, but its content adaptation was not queued",
45197
+ adaptation.queueFailure
45198
+ );
45199
+ return;
45200
+ }
45201
+ console.log(style.primary("Content adaptation"));
45202
+ for (const dataset of adaptation.datasets) {
45203
+ console.log(
45204
+ dataset.skipped ? ` ${datasetLabel(dataset)}: not adapted by this deploy (${dataset.skipReason ?? "skipped"})` : ` ${datasetLabel(dataset)}: queued as task ${dataset.taskId}`
45205
+ );
45206
+ }
45207
+ if (followUp !== null) console.log(style.muted(followUp));
45208
+ }
45209
+
45847
45210
  // src/commands/promote.ts
45848
45211
  init_exit_codes();
45849
45212
  async function resolveActiveSandbox(projectId) {
@@ -45897,6 +45260,27 @@ async function resolveWithEntries(options) {
45897
45260
  if (options.yes) return false;
45898
45261
  return confirm("Also apply your sandbox's writes to the target branch as changes?");
45899
45262
  }
45263
+ var PLAN_QUESTION = "Apply this plan to stored content and promote?";
45264
+ function reportPromotionFailure(error2, body) {
45265
+ out.error("Promotion failed", error2 instanceof Error ? error2.message : "Unknown error");
45266
+ const issues = issuesToValidationErrors(issuesOf(body));
45267
+ if (issues.length > 0) out.issues(issues);
45268
+ }
45269
+ async function readPromotePlan(projectId, sandboxBranchId, targetBranchId) {
45270
+ const spinner = out.spinner("Reading the plan...");
45271
+ try {
45272
+ const sandboxSchema = await schema_default.getCurrentSchema(projectId, sandboxBranchId);
45273
+ const plan = await planManifest(projectId, targetBranchId, {
45274
+ schema: sandboxSchema.schemaDefinition
45275
+ });
45276
+ spinner.stop();
45277
+ return plan;
45278
+ } catch (error2) {
45279
+ spinner.fail("Could not read the plan");
45280
+ reportPromotionFailure(error2, manageErrorBody(error2));
45281
+ throw exitWith(EXIT_ERROR);
45282
+ }
45283
+ }
45900
45284
  async function handlePromote(options) {
45901
45285
  const acceptPlanError = acceptPlanOptionError(options.acceptPlan);
45902
45286
  if (acceptPlanError !== void 0) {
@@ -45924,6 +45308,9 @@ async function handlePromote(options) {
45924
45308
  throw exitWith(EXIT_ERROR);
45925
45309
  }
45926
45310
  const withEntries = await resolveWithEntries(options);
45311
+ const asks = options.yes !== true && options.acceptPlan === void 0;
45312
+ const plan = asks ? await readPromotePlan(projectId, sandbox.branch.id, target.id) : void 0;
45313
+ const planToAccept = plan?.needsConfirmation === true ? plan : void 0;
45927
45314
  out.section("Promotion Plan", "sparkles");
45928
45315
  console.log(style.primary("\u2502 ") + style.muted(`Sandbox: ${sandbox.branch.name}`));
45929
45316
  console.log(style.primary("\u2502 ") + style.muted(`Target: ${target.name}`));
@@ -45933,14 +45320,24 @@ async function handlePromote(options) {
45933
45320
  );
45934
45321
  out.sectionEnd();
45935
45322
  console.log();
45323
+ if (plan && deployPlanHasContent(plan)) {
45324
+ console.log(formatDeployPlan(plan));
45325
+ console.log();
45326
+ }
45327
+ if (plan && plan.refusals.length > 0) {
45328
+ out.error("Not promoted", planRefusedMessage(plan, PROMOTE_COMMAND));
45329
+ throw exitWith(EXIT_ERROR);
45330
+ }
45936
45331
  if (!options.yes) {
45937
- const confirmed = await confirm(`Promote "${sandbox.branch.name}" into "${target.name}"?`);
45332
+ const confirmed = await confirm(
45333
+ planToAccept ? PLAN_QUESTION : `Promote "${sandbox.branch.name}" into "${target.name}"?`
45334
+ );
45938
45335
  if (!confirmed) {
45939
45336
  out.info("Promotion cancelled");
45940
45337
  throw exitWith(EXIT_ERROR);
45941
45338
  }
45942
45339
  }
45943
- let confirmPlan = options.acceptPlan;
45340
+ let confirmPlan = options.acceptPlan ?? planToAccept?.planId;
45944
45341
  let result;
45945
45342
  while (result === void 0) {
45946
45343
  const promoteSpinner = out.spinner("Promoting sandbox schema...");
@@ -45952,12 +45349,10 @@ async function handlePromote(options) {
45952
45349
  });
45953
45350
  } catch (error2) {
45954
45351
  const body = manageErrorBody(error2);
45955
- const blockage = planBlockageOf(body);
45352
+ const blockage = deployPlanBlockageOf(body);
45956
45353
  if (!blockage) {
45957
45354
  promoteSpinner.fail("Promotion failed");
45958
- out.error("Promotion failed", error2 instanceof Error ? error2.message : "Unknown error");
45959
- const issues = issuesToValidationErrors(issuesOf(body));
45960
- if (issues.length > 0) out.issues(issues);
45355
+ reportPromotionFailure(error2, body);
45961
45356
  throw exitWith(EXIT_ERROR);
45962
45357
  }
45963
45358
  promoteSpinner.fail("Not promoted: the plan was not accepted");
@@ -45966,7 +45361,7 @@ async function handlePromote(options) {
45966
45361
  if (!unattended) {
45967
45362
  out.warning(planBlockageHeadline(blockage, PROMOTE_COMMAND));
45968
45363
  }
45969
- console.log(formatAdaptationPlan(blockage.plan));
45364
+ console.log(formatDeployPlan(blockage.plan));
45970
45365
  console.log();
45971
45366
  if (unattended) {
45972
45367
  out.error(
@@ -45979,7 +45374,7 @@ async function handlePromote(options) {
45979
45374
  out.error("Not promoted", planRefusedMessage(blockage.plan, PROMOTE_COMMAND));
45980
45375
  throw exitWith(EXIT_ERROR);
45981
45376
  }
45982
- const accepted = await confirm("Apply this plan to stored content and promote?");
45377
+ const accepted = await confirm(PLAN_QUESTION);
45983
45378
  if (!accepted) {
45984
45379
  out.info("Promotion cancelled");
45985
45380
  throw exitWith(EXIT_ERROR);
@@ -45991,6 +45386,7 @@ async function handlePromote(options) {
45991
45386
  result.schemaChanged ? `Schema deployed to "${target.name}"${result.deployedVersion ? ` (v${result.deployedVersion})` : ""}` : `Schema already in sync with "${target.name}"`
45992
45387
  );
45993
45388
  }
45389
+ if (result.adaptation) displayQueuedAdaptation(result.adaptation, null);
45994
45390
  if (result.entriesTaskId) {
45995
45391
  const entriesSpinner = out.spinner("Applying sandbox writes as changes...");
45996
45392
  const final = await pollTaskUntilDone(projectId, result.entriesTaskId, {
@@ -46057,9 +45453,10 @@ Notes:
46057
45453
  \u2022 If the target branch changed since your sandbox forked, promotion is blocked and
46058
45454
  you'll be asked to rebase (start a fresh \`relyio dev\` from the updated branch).
46059
45455
  \u2022 A sandbox schema that would delete, archive or fill the target's stored content
46060
- prints its plan first. Interactively you are asked to apply it; -y never accepts
46061
- a plan, so it exits 1 naming --accept-plan <planId>. Nothing is promoted until
46062
- the plan is accepted.
45456
+ prints its plan first, and you are asked once, with the plan in front of you. -y
45457
+ never accepts a plan, so it exits 1 naming --accept-plan <planId>. Nothing is
45458
+ promoted until the plan is accepted.
45459
+ \u2022 The adaptation the promote queues in the target's datasets is reported per dataset.
46063
45460
  `
46064
45461
  );
46065
45462
  }
@@ -46091,15 +45488,10 @@ async function offerPromoteWhenSandboxActive() {
46091
45488
  }
46092
45489
 
46093
45490
  // src/commands/deploy.ts
46094
- init_adaptation_plan();
45491
+ init_deploy_plan();
46095
45492
  init_exit_codes();
46096
45493
  function formatSchemaSource(preview2) {
46097
- if (preview2.schemaSourceType === "typescript") {
46098
- const relativePath = preview2.schemaSourcePath.replace(process.cwd() + "/", "");
46099
- return `TypeScript (${relativePath})`;
46100
- }
46101
- const files = preview2.schemaSourcePath;
46102
- return `YAML (${files.length} file${files.length === 1 ? "" : "s"})`;
45494
+ return preview2.schemaSourcePath.replace(process.cwd() + "/", "");
46103
45495
  }
46104
45496
  function interrupted(json) {
46105
45497
  if (json) {
@@ -46273,14 +45665,14 @@ async function handleDeploy(options) {
46273
45665
  }
46274
45666
  }
46275
45667
  const plan = previewData.plan;
46276
- if (!json && plan && planHasContent(plan)) {
45668
+ if (!json && plan && deployPlanHasContent(plan)) {
46277
45669
  console.log();
46278
- console.log(formatAdaptationPlan(plan));
45670
+ console.log(formatDeployPlan(plan));
46279
45671
  }
46280
45672
  if (plan && plan.refusals.length > 0) return planRefused(plan, previewData, json);
46281
45673
  const planToAccept = plan?.needsConfirmation === true ? plan : void 0;
46282
45674
  if (planToAccept && options.acceptPlan === void 0 && (json || options.yes)) {
46283
- return planNotAccepted({ kind: "schema-plan-unconfirmed", plan: planToAccept }, previewData, {
45675
+ return planNotAccepted({ kind: "manifest-plan-unconfirmed", plan: planToAccept }, previewData, {
46284
45676
  json,
46285
45677
  printed: true
46286
45678
  });
@@ -46295,7 +45687,7 @@ async function handleDeploy(options) {
46295
45687
  {
46296
45688
  type: "confirm",
46297
45689
  name: "confirmed",
46298
- message: chalk10.bold(
45690
+ message: chalk12.bold(
46299
45691
  acceptsPlanHere ? "Deploy these changes and apply the plan above to stored content?" : "Deploy these changes to your branch?"
46300
45692
  ),
46301
45693
  default: false
@@ -46314,8 +45706,8 @@ async function handleDeploy(options) {
46314
45706
  {
46315
45707
  type: "input",
46316
45708
  name: "notes",
46317
- message: chalk10.bold("Add deployment notes (optional):"),
46318
- transformer: (input) => input.length > 0 ? chalk10.cyan(input) : chalk10.gray("(none)")
45709
+ message: chalk12.bold("Add deployment notes (optional):"),
45710
+ transformer: (input) => input.length > 0 ? chalk12.cyan(input) : chalk12.gray("(none)")
46319
45711
  }
46320
45712
  ]),
46321
45713
  json
@@ -46330,7 +45722,7 @@ async function handleDeploy(options) {
46330
45722
  if (!interactive) return planNotAccepted(blockage, previewData, { json, printed: false });
46331
45723
  console.log();
46332
45724
  out.warning(planBlockageHeadline(blockage, DEPLOY_COMMAND));
46333
- console.log(formatAdaptationPlan(blockage.plan));
45725
+ console.log(formatDeployPlan(blockage.plan));
46334
45726
  if (blockage.plan.refusals.length > 0) return planRefused(blockage.plan, previewData, json);
46335
45727
  console.log();
46336
45728
  const { confirmed } = await orInterrupted(
@@ -46338,7 +45730,7 @@ async function handleDeploy(options) {
46338
45730
  {
46339
45731
  type: "confirm",
46340
45732
  name: "confirmed",
46341
- message: chalk10.bold("Apply this plan to stored content and deploy?"),
45733
+ message: chalk12.bold("Apply this plan to stored content and deploy?"),
46342
45734
  default: false
46343
45735
  }
46344
45736
  ]),
@@ -46416,7 +45808,8 @@ async function handleDeploy(options) {
46416
45808
  if (unseenWarnings.length > 0) {
46417
45809
  out.issues(unseenWarnings, "warning");
46418
45810
  }
46419
- if (result.adaptation) displayQueuedAdaptation(result.adaptation, options.wait === true);
45811
+ if (result.adaptation)
45812
+ displayQueuedAdaptation(result.adaptation, options.wait === true ? null : ADAPTATION_FOLLOW_UP);
46420
45813
  if (waited) {
46421
45814
  displayAdaptationOutcome(waited.waited, waited.verdict);
46422
45815
  if (!waited.verdict.ok) throw exitWith(EXIT_ERROR);
@@ -46497,19 +45890,19 @@ function planNotAccepted(blockage, previewData, options) {
46497
45890
  return out.jsonFailure(
46498
45891
  {
46499
45892
  message,
46500
- code: blockage.kind === "schema-plan-stale" ? "PLAN_STALE" : "PLAN_UNCONFIRMED"
45893
+ code: blockage.kind === "manifest-plan-stale" ? "PLAN_STALE" : "PLAN_UNCONFIRMED"
46501
45894
  },
46502
45895
  {
46503
45896
  branch: { name: previewData.branchName, id: previewData.branchId },
46504
45897
  plan,
46505
- ...blockage.kind === "schema-plan-stale" ? { confirmedPlanId: blockage.confirmedPlanId } : {},
45898
+ ...blockage.kind === "manifest-plan-stale" ? { confirmedPlanId: blockage.confirmedPlanId } : {},
46506
45899
  acceptWith: accept
46507
45900
  }
46508
45901
  );
46509
45902
  }
46510
45903
  if (!options.printed) {
46511
45904
  console.log();
46512
- console.log(formatAdaptationPlan(plan));
45905
+ console.log(formatDeployPlan(plan));
46513
45906
  }
46514
45907
  console.log();
46515
45908
  out.error("Not deployed: the plan was not accepted", message);
@@ -46525,15 +45918,15 @@ function judgeAdaptation(waited, adaptation) {
46525
45918
  }
46526
45919
  const reported = new Map(waited.status.adaptations.map((entry) => [entry.taskId, entry.status]));
46527
45920
  const queued = adaptation.datasets.filter((dataset) => dataset.skipped !== true);
46528
- const failed3 = queued.filter((dataset) => {
45921
+ const failed4 = queued.filter((dataset) => {
46529
45922
  const status = reported.get(dataset.taskId);
46530
45923
  return status === "failed" || status === "rolled_back";
46531
45924
  });
46532
- if (failed3.length > 0) {
45925
+ if (failed4.length > 0) {
46533
45926
  return {
46534
45927
  ok: false,
46535
45928
  code: "ADAPTATION_FAILED",
46536
- message: `The schema deployed; its content adaptation failed in ${failed3.map((dataset) => datasetLabel(dataset)).join(", ")}.`
45929
+ message: `The schema deployed; its content adaptation failed in ${failed4.map((dataset) => datasetLabel(dataset)).join(", ")}.`
46537
45930
  };
46538
45931
  }
46539
45932
  const unreported = queued.filter((dataset) => reported.get(dataset.taskId) !== "completed");
@@ -46554,32 +45947,7 @@ async function waitWithProgress(previewData, adaptation, json) {
46554
45947
  else spinner?.fail("Content adaptation did not finish");
46555
45948
  return { waited, verdict };
46556
45949
  }
46557
- function datasetLabel(dataset) {
46558
- return dataset.datasetName === null ? dataset.datasetId : `${dataset.datasetName} (${dataset.datasetId})`;
46559
- }
46560
- function displayQueuedAdaptation(adaptation, waiting) {
46561
- console.log();
46562
- if (adaptation.queueFailure !== void 0) {
46563
- out.warning(
46564
- "The schema deployed, but its content adaptation was not queued",
46565
- adaptation.queueFailure
46566
- );
46567
- return;
46568
- }
46569
- console.log(style.primary("Content adaptation"));
46570
- for (const dataset of adaptation.datasets) {
46571
- console.log(
46572
- dataset.skipped ? ` ${datasetLabel(dataset)}: not adapted by this deploy (${dataset.skipReason ?? "skipped"})` : ` ${datasetLabel(dataset)}: queued as task ${dataset.taskId}`
46573
- );
46574
- }
46575
- if (!waiting) {
46576
- console.log(
46577
- style.muted(
46578
- " It runs in the background; reads serve the new schema meanwhile. `relyio deploy --wait` waits for it to finish."
46579
- )
46580
- );
46581
- }
46582
- }
45950
+ var ADAPTATION_FOLLOW_UP = " It runs in the background; reads serve the new schema meanwhile. `relyio deploy --wait` waits for it to finish.";
46583
45951
  function displayAdaptationOutcome(waited, verdict) {
46584
45952
  for (const adaptation of waited.status.adaptations) {
46585
45953
  console.log(` ${datasetLabel(adaptation)}: ${adaptation.status}`);
@@ -46595,7 +45963,7 @@ function deployCommand(program2) {
46595
45963
  });
46596
45964
  command.option("-b, --branch <branch>", "Target branch (defaults to current branch)").option("-y, --yes", "Skip confirmation prompt").option("--skip-notes", "Skip deployment notes prompt").option("--json", "Output result as JSON (for CI/CD integration)").option(
46597
45965
  "--accept-plan <planId>",
46598
- "Accept this adaptation plan without a question (a deploy that deletes or archives content needs it with -y or --json)"
45966
+ "Accept this plan without a question: the Manifest plan's id, as `relyio plan` prints it (a deploy that deletes or archives content needs it with -y or --json)"
46599
45967
  ).option("--wait", "Wait for the content adaptation the deploy queues to finish");
46600
45968
  command.addHelpText(
46601
45969
  "after",
@@ -46606,7 +45974,7 @@ Examples:
46606
45974
  $ relyio deploy -b main # Deploy to main branch
46607
45975
  $ relyio deploy --json # CI/CD mode (auto-confirm, JSON output)
46608
45976
  $ relyio deploy --json --accept-plan <planId>
46609
- # CI/CD, accepting the plan \`relyio diff --json\` printed
45977
+ # CI/CD, accepting the plan \`relyio plan --json\` printed
46610
45978
  $ relyio deploy --wait # Wait for the content adaptation to finish
46611
45979
 
46612
45980
  Plans:
@@ -46618,7 +45986,8 @@ Plans:
46618
45986
  Workflow:
46619
45987
  1. Check status: relyio status
46620
45988
  2. Review diff: relyio diff
46621
- 3. Deploy changes: relyio deploy
45989
+ 3. Read the plan: relyio plan
45990
+ 4. Deploy changes: relyio deploy
46622
45991
  `
46623
45992
  );
46624
45993
  }
@@ -47145,7 +46514,7 @@ function sandboxCommands(program2) {
47145
46514
  }
47146
46515
 
47147
46516
  // src/commands/version.ts
47148
- var CLI_VERSION = "0.11.0" ;
46517
+ var CLI_VERSION = "0.12.0" ;
47149
46518
  async function handleVersion(_options) {
47150
46519
  out.heading("RelyIO CLI Version Information");
47151
46520
  const versionInfo = [
@@ -47342,7 +46711,7 @@ function statusFailure(context) {
47342
46711
  return { code: "SCHEMA_INVALID", message: context.schemaLoadError };
47343
46712
  }
47344
46713
  if (!context.localSchema) {
47345
- return { code: "SCHEMA_NOT_FOUND", message: "No schema found" };
46714
+ return { code: "SCHEMA_NOT_FOUND", message: context.schemaNotTypeScript ?? "No schema found" };
47346
46715
  }
47347
46716
  if (!context.status) {
47348
46717
  return { code: "STATUS_CHECK_FAILED", message: "The status check returned no status" };
@@ -47366,13 +46735,7 @@ function messageOf(error2) {
47366
46735
  return error2 instanceof Error ? error2.message : String(error2);
47367
46736
  }
47368
46737
  function formatSchemaSource2(result) {
47369
- if (result.sourceType === "typescript") {
47370
- const relativePath = result.sourcePath.replace(process.cwd() + "/", "");
47371
- return `TypeScript (${relativePath})`;
47372
- }
47373
- const files = result.sourcePath;
47374
- const count2 = files.length;
47375
- return `YAML (${count2} file${count2 === 1 ? "" : "s"})`;
46738
+ return result.sourcePath.replace(process.cwd() + "/", "");
47376
46739
  }
47377
46740
  async function performStatusCheck(branchName, options) {
47378
46741
  const { json = false, verbose = false, watch: watchMode = false } = options;
@@ -47443,23 +46806,27 @@ async function performStatusCheck(branchName, options) {
47443
46806
  ctx.schemaLoadError = messageOf(error2);
47444
46807
  throw error2;
47445
46808
  }
47446
- if (!detection.sourceType) {
46809
+ if (detection.sourcePath === null) {
46810
+ if (detection.yamlFiles.length > 0) {
46811
+ ctx.schemaNotTypeScript = new SchemaNotFoundError(
46812
+ process.cwd(),
46813
+ detection.yamlFiles
46814
+ ).message;
46815
+ }
47447
46816
  task.title = "No schema found";
47448
46817
  return;
47449
46818
  }
47450
- ctx.schemaSourceType = detection.sourceType;
47451
46819
  ctx.schemaSourcePath = detection.sourcePath;
47452
46820
  task.title = `Detected ${detection.description} (${formatDuration(performance.now() - start)})`;
47453
46821
  }
47454
46822
  },
47455
46823
  {
47456
46824
  title: "Loading schema",
47457
- skip: (ctx) => !ctx.branchId || !ctx.schemaSourceType,
46825
+ skip: (ctx) => !ctx.branchId || ctx.schemaSourcePath === void 0,
47458
46826
  task: async (ctx, task) => {
47459
46827
  const start = performance.now();
47460
46828
  try {
47461
46829
  const result = await loadSchema();
47462
- ctx.schemaSourceType = result.sourceType;
47463
46830
  ctx.schemaSourcePath = result.sourcePath;
47464
46831
  if (result.warnings && result.warnings.length > 0) {
47465
46832
  ctx.schemaLoaderWarnings = result.warnings;
@@ -47585,8 +46952,7 @@ async function performStatusCheck(branchName, options) {
47585
46952
  const jsonOutput = createStatusJsonOutput({
47586
46953
  branchName: context.branchName || branchName,
47587
46954
  branchId: context.branchId,
47588
- schemaSourceType: context.schemaSourceType || "yaml",
47589
- schemaSourcePath: context.schemaSourcePath || "",
46955
+ schemaSourcePath: context.schemaSourcePath ?? null,
47590
46956
  gitCommitSha: gitSha || void 0,
47591
46957
  hasChanges: context.status?.hasChanges ?? false,
47592
46958
  changes: context.status,
@@ -47634,7 +47000,7 @@ function displayCompactStatus(context, failure) {
47634
47000
  if (failure?.code === "SCHEMA_INVALID" || failure?.code === "SCHEMA_NOT_FOUND") {
47635
47001
  out.line(
47636
47002
  "error",
47637
- failure.code === "SCHEMA_NOT_FOUND" ? "No local schema found" : failure.message
47003
+ failure.code === "SCHEMA_NOT_FOUND" ? context.schemaNotTypeScript ?? "No local schema found" : failure.message
47638
47004
  );
47639
47005
  return;
47640
47006
  }
@@ -47685,10 +47051,8 @@ async function displayVerboseStatus(context, failure, watchMode) {
47685
47051
  out.error("Schema status check failed", failure.message);
47686
47052
  return;
47687
47053
  }
47688
- if (context.schemaSourceType) {
47689
- const sourceLabel = context.schemaSourceType === "typescript" ? "TypeScript" : "YAML";
47690
- const sourcePath = context.schemaSourceType === "typescript" ? context.schemaSourcePath.replace(process.cwd() + "/", "") : `${context.schemaSourcePath.length} files`;
47691
- out.info(`Schema: ${sourceLabel} (${sourcePath})`, "file");
47054
+ if (context.schemaSourcePath !== void 0) {
47055
+ out.info(`Schema: ${formatSchemaSource2({ sourcePath: context.schemaSourcePath })}`, "file");
47692
47056
  }
47693
47057
  if (context.schemaLoaderWarnings?.length) {
47694
47058
  for (const warning of context.schemaLoaderWarnings) {
@@ -47752,7 +47116,7 @@ async function displayVerboseStatus(context, failure, watchMode) {
47752
47116
  return;
47753
47117
  }
47754
47118
  if (failure?.code === "SCHEMA_NOT_FOUND") {
47755
- out.error("No local schema found in the current directory");
47119
+ out.error(context.schemaNotTypeScript ?? "No local schema found in the current directory");
47756
47120
  return;
47757
47121
  }
47758
47122
  if (failure?.code === "SCHEMA_INVALID") {
@@ -47827,10 +47191,8 @@ async function handleStatus(options) {
47827
47191
  }
47828
47192
  });
47829
47193
  const detection = await detectSchemaSource();
47830
- if (detection.sourceType) {
47831
- out.info(
47832
- `Watching ${detection.sourceType === "typescript" ? "TypeScript" : "YAML"} schema files for changes...`
47833
- );
47194
+ if (detection.sourcePath !== null) {
47195
+ out.info("Watching TypeScript schema files for changes...");
47834
47196
  }
47835
47197
  watcher.start();
47836
47198
  return;
@@ -48003,13 +47365,13 @@ init_manage();
48003
47365
  init_manage_error();
48004
47366
  init_dist5();
48005
47367
  async function writeFiles(files, outputDir) {
48006
- await fs4.mkdir(outputDir, { recursive: true });
47368
+ await fs3.mkdir(outputDir, { recursive: true });
48007
47369
  await Promise.all(
48008
47370
  files.map(async (file) => {
48009
47371
  const fullPath = path5.join(outputDir, file.path);
48010
47372
  const dir = path5.dirname(fullPath);
48011
- await fs4.mkdir(dir, { recursive: true });
48012
- await fs4.writeFile(fullPath, file.content, "utf8");
47373
+ await fs3.mkdir(dir, { recursive: true });
47374
+ await fs3.writeFile(fullPath, file.content, "utf8");
48013
47375
  })
48014
47376
  );
48015
47377
  }
@@ -48102,7 +47464,7 @@ async function findCodegenConfig(directory) {
48102
47464
  for (const name of CODEGEN_CONFIG_FILES) {
48103
47465
  const candidate = path5.join(directory, name);
48104
47466
  try {
48105
- await fs4.access(candidate);
47467
+ await fs3.access(candidate);
48106
47468
  return candidate;
48107
47469
  } catch {
48108
47470
  }
@@ -48113,7 +47475,7 @@ async function loadCodegenConfig(configPath) {
48113
47475
  const targetPath = configPath ?? await findCodegenConfig(process.cwd());
48114
47476
  if (targetPath === void 0) return {};
48115
47477
  try {
48116
- const content = await fs4.readFile(targetPath, "utf8");
47478
+ const content = await fs3.readFile(targetPath, "utf8");
48117
47479
  return parseCodegenConfig(content);
48118
47480
  } catch (error2) {
48119
47481
  if (configPath) {
@@ -48126,13 +47488,7 @@ async function loadCodegenConfig(configPath) {
48126
47488
  // src/commands/generate-types.ts
48127
47489
  init_exit_codes();
48128
47490
  function formatSchemaSource3(result) {
48129
- if (result.sourceType === "typescript") {
48130
- const relativePath = result.sourcePath.replace(process.cwd() + "/", "");
48131
- return `TypeScript (${relativePath})`;
48132
- }
48133
- const files = result.sourcePath;
48134
- const count2 = files.length;
48135
- return `YAML (${count2} file${count2 === 1 ? "" : "s"})`;
47491
+ return result.sourcePath.replace(process.cwd() + "/", "");
48136
47492
  }
48137
47493
  function handleGenerationError(error2) {
48138
47494
  if (error2 instanceof Error) {
@@ -48228,10 +47584,9 @@ async function performTypeGeneration(branchName, options, watchMode = false) {
48228
47584
  title: "Detecting schema source",
48229
47585
  task: async (ctx, task) => {
48230
47586
  const detection = await detectSchemaSource();
48231
- if (!detection.sourceType) {
48232
- throw new SchemaNotFoundError(process.cwd());
47587
+ if (detection.sourcePath === null) {
47588
+ throw new SchemaNotFoundError(process.cwd(), detection.yamlFiles);
48233
47589
  }
48234
- ctx.schemaSourceType = detection.sourceType;
48235
47590
  ctx.schemaSourcePath = detection.sourcePath;
48236
47591
  task.title = `Detected ${detection.description}`;
48237
47592
  }
@@ -48240,7 +47595,6 @@ async function performTypeGeneration(branchName, options, watchMode = false) {
48240
47595
  title: "Loading and validating schema",
48241
47596
  task: async (ctx, task) => {
48242
47597
  const result = await loadSchema();
48243
- ctx.schemaSourceType = result.sourceType;
48244
47598
  ctx.schemaSourcePath = result.sourcePath;
48245
47599
  if (result.warnings && result.warnings.length > 0) {
48246
47600
  ctx.schemaLoaderWarnings = result.warnings;
@@ -48295,10 +47649,8 @@ async function performTypeGeneration(branchName, options, watchMode = false) {
48295
47649
  );
48296
47650
  try {
48297
47651
  const ctx = await tasks.run();
48298
- if (ctx.schemaSourceType) {
48299
- const sourceLabel = ctx.schemaSourceType === "typescript" ? "TypeScript" : "YAML";
48300
- const sourcePath = ctx.schemaSourceType === "typescript" ? ctx.schemaSourcePath.replace(process.cwd() + "/", "") : `${ctx.schemaSourcePath.length} files`;
48301
- out.info(`Schema: ${sourceLabel} (${sourcePath})`, "file");
47652
+ if (ctx.schemaSourcePath !== void 0) {
47653
+ out.info(`Schema: ${formatSchemaSource3({ sourcePath: ctx.schemaSourcePath })}`, "file");
48302
47654
  }
48303
47655
  if (ctx.schemaLoaderWarnings?.length) {
48304
47656
  for (const warning of ctx.schemaLoaderWarnings) {
@@ -48357,10 +47709,8 @@ async function handleGenerateTypes(options) {
48357
47709
  }
48358
47710
  });
48359
47711
  const detection = await detectSchemaSource();
48360
- if (detection.sourceType) {
48361
- out.info(
48362
- `Watching ${detection.sourceType === "typescript" ? "TypeScript" : "YAML"} schema files for changes...`
48363
- );
47712
+ if (detection.sourcePath !== null) {
47713
+ out.info("Watching TypeScript schema files for changes...");
48364
47714
  }
48365
47715
  watcher.start();
48366
47716
  return;
@@ -48411,16 +47761,16 @@ Configuration:
48411
47761
  }
48412
47762
  init_diff_service();
48413
47763
  init_change_buckets();
48414
- init_adaptation_plan();
47764
+ init_deploy_plan();
48415
47765
  init_exit_codes();
48416
47766
  var THEME = {
48417
- added: chalk10.green,
48418
- removed: chalk10.red,
48419
- modified: chalk10.yellow,
48420
- muted: chalk10.gray,
48421
- bold: chalk10.bold,
48422
- dim: chalk10.dim,
48423
- cyan: chalk10.cyan
47767
+ added: chalk12.green,
47768
+ removed: chalk12.red,
47769
+ modified: chalk12.yellow,
47770
+ muted: chalk12.gray,
47771
+ bold: chalk12.bold,
47772
+ dim: chalk12.dim,
47773
+ cyan: chalk12.cyan
48424
47774
  };
48425
47775
  function displayDiffHeader(branchName, branchId) {
48426
47776
  console.log();
@@ -48657,7 +48007,6 @@ async function handleDiff(options) {
48657
48007
  createDiffJsonOutput({
48658
48008
  branchName: result.branchName,
48659
48009
  branchId: result.branchId,
48660
- schemaSourceType: result.schemaSourceType,
48661
48010
  schemaSourcePath: result.schemaSourcePath,
48662
48011
  hasChanges: result.hasChanges,
48663
48012
  changes: result.changes,
@@ -48676,8 +48025,8 @@ async function handleDiff(options) {
48676
48025
  console.log(THEME.muted("No changes between local schema and remote branch"));
48677
48026
  console.log();
48678
48027
  }
48679
- if (result.plan && planHasContent(result.plan)) {
48680
- console.log(formatAdaptationPlan(result.plan));
48028
+ if (result.plan && deployPlanHasContent(result.plan)) {
48029
+ console.log(formatDeployPlan(result.plan));
48681
48030
  console.log();
48682
48031
  }
48683
48032
  if (result.validationWarnings.length > 0) {
@@ -48757,6 +48106,227 @@ Output Format:
48757
48106
  );
48758
48107
  }
48759
48108
 
48109
+ // src/services/plan.service.ts
48110
+ init_config();
48111
+ init_manifest();
48112
+ init_manage();
48113
+ init_manage_error();
48114
+ init_schema_loader();
48115
+ init_git();
48116
+ function failed3(error2) {
48117
+ return { status: "failed", error: error2 };
48118
+ }
48119
+ async function readManifest(projectRoot) {
48120
+ try {
48121
+ const loaded = await loadSchema(projectRoot);
48122
+ if (loaded.errors.length > 0) {
48123
+ return {
48124
+ message: `Schema has ${loaded.errors.length} validation error(s).`,
48125
+ code: "SCHEMA_INVALID",
48126
+ validationErrors: loaded.errors.map((error2) => ({
48127
+ path: error2.file,
48128
+ message: error2.error,
48129
+ severity: "error"
48130
+ }))
48131
+ };
48132
+ }
48133
+ return { schema: loaded.schema };
48134
+ } catch (error2) {
48135
+ if (error2 instanceof SchemaNotFoundError) {
48136
+ return { message: error2.message, code: "SCHEMA_NOT_FOUND" };
48137
+ }
48138
+ return {
48139
+ message: error2 instanceof Error ? error2.message : "Failed to load schema",
48140
+ code: "SCHEMA_INVALID"
48141
+ };
48142
+ }
48143
+ }
48144
+ function apiError(error2) {
48145
+ const body = manageErrorBody(error2);
48146
+ const validationErrors = issuesToValidationErrors(issuesOf(body));
48147
+ const summary = body?.error.messages?.[0];
48148
+ if (validationErrors.length > 0) {
48149
+ return { message: summary ?? "Validation failed", code: "VALIDATION_FAILED", validationErrors };
48150
+ }
48151
+ return {
48152
+ message: summary ?? (error2 instanceof Error ? error2.message : "Could not read the plan"),
48153
+ code: "API_ERROR"
48154
+ };
48155
+ }
48156
+ async function run3(options) {
48157
+ let branchName;
48158
+ try {
48159
+ branchName = await determineBranchName({ branch: options.branchName });
48160
+ } catch (error2) {
48161
+ return failed3({
48162
+ message: error2 instanceof Error ? error2.message : "Failed to determine branch name",
48163
+ code: "BRANCH_DETECTION_FAILED"
48164
+ });
48165
+ }
48166
+ const projectId = config_default.getProjectId();
48167
+ if (!projectId) {
48168
+ return failed3({
48169
+ message: "No project linked. Run 'relyio link' first.",
48170
+ code: "NO_PROJECT_LINKED"
48171
+ });
48172
+ }
48173
+ let branchId;
48174
+ try {
48175
+ const [branch] = await manage_default.getProjectBranches(projectId, { name: branchName });
48176
+ if (!branch) {
48177
+ return failed3({ message: `Branch '${branchName}' not found.`, code: "BRANCH_NOT_FOUND" });
48178
+ }
48179
+ branchId = branch.id;
48180
+ } catch (error2) {
48181
+ return failed3(apiError(error2));
48182
+ }
48183
+ const manifest = await readManifest(options.projectRoot);
48184
+ if ("code" in manifest) return failed3(manifest);
48185
+ try {
48186
+ return {
48187
+ status: "ok",
48188
+ branchName,
48189
+ branchId,
48190
+ plan: await planManifest(projectId, branchId, manifest)
48191
+ };
48192
+ } catch (error2) {
48193
+ return failed3(apiError(error2));
48194
+ }
48195
+ }
48196
+ var ACTION_MARK = {
48197
+ create: chalk12.green("+"),
48198
+ change: chalk12.yellow("~"),
48199
+ delete: chalk12.red("-")
48200
+ };
48201
+ var ENVIRONMENT_LABEL = {
48202
+ production: "Production",
48203
+ preview: "Preview"
48204
+ };
48205
+ function plural4(count2, noun) {
48206
+ return `${count2} ${noun}${count2 === 1 ? "" : "s"}`;
48207
+ }
48208
+ function lineLines(line) {
48209
+ const marker = line.deletesOrRewritesData ? ` ${chalk12.red("deletes or rewrites data")}` : "";
48210
+ return [
48211
+ ` ${ACTION_MARK[line.action]} ${line.note}${marker}`,
48212
+ ...line.details.map((detail) => ` ${chalk12.gray(detail)}`)
48213
+ ];
48214
+ }
48215
+ function areaLines(area) {
48216
+ const heading = area.lines.length === 0 ? `${chalk12.bold(area.label)} \u2014 no change` : `${chalk12.bold(area.label)} \u2014 ${plural4(area.lines.length, "change")}`;
48217
+ return [heading, ...area.lines.flatMap((line) => lineLines(line))];
48218
+ }
48219
+ function environmentLines(title, lines) {
48220
+ if (lines.length === 0) return [];
48221
+ return [
48222
+ "",
48223
+ chalk12.bold(title),
48224
+ ...lines.map((line) => ` ${ENVIRONMENT_LABEL[line.environment]}: ${line.item} \u2014 ${line.note}`)
48225
+ ];
48226
+ }
48227
+ function labelOf(plan, area) {
48228
+ return plan.areas.find((candidate) => candidate.area === area)?.label ?? area;
48229
+ }
48230
+ function formatManifestPlan(plan) {
48231
+ const lines = plan.areas.flatMap((area) => areaLines(area));
48232
+ if (plan.refusals.length > 0) {
48233
+ lines.push("", chalk12.red.bold("Deploy would refuse this plan:"));
48234
+ for (const refusal2 of plan.refusals) {
48235
+ lines.push(
48236
+ ` ${chalk12.red("\u2717")} ${labelOf(plan, refusal2.area)}: ${refusal2.code} \u2014 ${refusal2.message}`
48237
+ );
48238
+ }
48239
+ }
48240
+ lines.push(
48241
+ ...environmentLines("Needs connecting:", plan.needsConnecting),
48242
+ ...environmentLines("Deploys paused:", plan.deploysPaused),
48243
+ "",
48244
+ confirmationLine(plan),
48245
+ chalk12.gray(`Plan ${plan.planId}`)
48246
+ );
48247
+ return lines.join("\n");
48248
+ }
48249
+ function confirmationLine(plan) {
48250
+ if (!plan.needsConfirmation) return "Nothing deletes or rewrites data.";
48251
+ const count2 = plan.areas.flatMap((area) => area.lines).filter((line) => line.deletesOrRewritesData).length;
48252
+ if (count2 === 0) {
48253
+ return chalk12.yellow(
48254
+ "Deploying it needs confirming: what it does to stored data could not all be counted."
48255
+ );
48256
+ }
48257
+ const verbs = count2 === 1 ? "deletes or rewrites" : "delete or rewrite";
48258
+ return chalk12.yellow(`${plural4(count2, "change")} ${verbs} data: deploying it needs confirming.`);
48259
+ }
48260
+
48261
+ // src/commands/plan.ts
48262
+ init_exit_codes();
48263
+ async function handlePlan(options) {
48264
+ const json = options.json ?? false;
48265
+ const result = await run3({ projectRoot: process.cwd(), branchName: options.branch });
48266
+ if (result.status === "failed") {
48267
+ const { error: error2 } = result;
48268
+ if (json) {
48269
+ if (error2.validationErrors?.length) {
48270
+ out.jsonFailure(
48271
+ { message: error2.message, code: error2.code },
48272
+ { validationErrors: error2.validationErrors }
48273
+ );
48274
+ }
48275
+ throw fail(error2.message, error2.code);
48276
+ }
48277
+ if (error2.validationErrors?.length) {
48278
+ out.issues(error2.validationErrors);
48279
+ throw exitWith(EXIT_ERROR);
48280
+ }
48281
+ throw fail(error2.message, error2.code);
48282
+ }
48283
+ const refused = result.plan.refusals.length > 0;
48284
+ if (json) {
48285
+ out.json(
48286
+ {
48287
+ success: true,
48288
+ branchName: result.branchName,
48289
+ branchId: result.branchId,
48290
+ plan: result.plan
48291
+ },
48292
+ refused ? EXIT_BLOCKED : void 0
48293
+ );
48294
+ }
48295
+ console.log();
48296
+ console.log(`Plan for ${result.branchName} (${result.branchId.slice(0, 8)})`);
48297
+ console.log();
48298
+ console.log(formatManifestPlan(result.plan));
48299
+ console.log();
48300
+ if (refused) throw exitWith(EXIT_BLOCKED);
48301
+ }
48302
+ function planCommand(program2) {
48303
+ const command = defineCommand(program2, {
48304
+ name: "plan",
48305
+ description: "Show what deploying the project to a branch would change, area by area, without deploying",
48306
+ auth: true,
48307
+ handler: handlePlan
48308
+ });
48309
+ command.option("-b, --branch <branch>", "Branch to plan for (defaults to the current Git branch)");
48310
+ command.option(
48311
+ "--json",
48312
+ "Print the Plan as JSON: the dry run an agent takes before a pull request"
48313
+ );
48314
+ command.addHelpText(
48315
+ "after",
48316
+ `
48317
+ Examples:
48318
+ $ relyio plan # Plan for the current branch
48319
+ $ relyio plan -b main # Plan for main
48320
+ $ relyio plan --json # The Plan as JSON, for an agent or a script
48321
+
48322
+ Each area lists one line per item it creates (+), changes (~) or deletes (-). A line that deletes
48323
+ or rewrites stored data needs confirming before it deploys; the plan says plainly when none does.
48324
+
48325
+ Exit codes: 0 a plan, 2 deploy would refuse it, 1 no plan could be read.
48326
+ `
48327
+ );
48328
+ }
48329
+
48760
48330
  // src/commands/doctor.ts
48761
48331
  init_dist2();
48762
48332
  init_config();
@@ -48765,11 +48335,11 @@ init_transport();
48765
48335
  init_schema_loader();
48766
48336
  init_exit_codes();
48767
48337
  var THEME2 = {
48768
- pass: chalk10.green,
48769
- warn: chalk10.yellow,
48770
- fail: chalk10.red,
48771
- muted: chalk10.gray,
48772
- bold: chalk10.bold
48338
+ pass: chalk12.green,
48339
+ warn: chalk12.yellow,
48340
+ fail: chalk12.red,
48341
+ muted: chalk12.gray,
48342
+ bold: chalk12.bold
48773
48343
  };
48774
48344
  var ICONS = {
48775
48345
  pass: "\u2713",
@@ -48976,26 +48546,23 @@ async function checkProjectLink() {
48976
48546
  async function checkSchemaFiles() {
48977
48547
  try {
48978
48548
  const detection = await detectSchemaSource();
48979
- if (!detection.sourceType) {
48980
- return {
48549
+ if (detection.sourcePath === null) {
48550
+ return detection.yamlFiles.length > 0 ? {
48551
+ name: "Schema files",
48552
+ status: "fail",
48553
+ message: `${detection.description}: TypeScript is the only schema source`,
48554
+ suggestion: "Write the schema in relyio/schema.ts with @relyio/sdk/schema"
48555
+ } : {
48981
48556
  name: "Schema files",
48982
48557
  status: "warn",
48983
48558
  message: "No schema files found",
48984
- suggestion: "Create relyio/schema.ts or YAML files in relyio/"
48985
- };
48986
- }
48987
- if (detection.sourceType === "typescript") {
48988
- return {
48989
- name: "Schema files",
48990
- status: "pass",
48991
- message: `TypeScript schema at ${detection.sourcePath.replace(process.cwd() + "/", "")}`
48559
+ suggestion: "Create relyio/schema.ts, or run relyio init --example blog"
48992
48560
  };
48993
48561
  }
48994
- const files = detection.sourcePath;
48995
48562
  return {
48996
48563
  name: "Schema files",
48997
48564
  status: "pass",
48998
- message: `${files.length} YAML file${files.length === 1 ? "" : "s"} found`
48565
+ message: `TypeScript schema at ${detection.sourcePath.replace(process.cwd() + "/", "")}`
48999
48566
  };
49000
48567
  } catch (error2) {
49001
48568
  return {
@@ -49050,10 +48617,10 @@ async function handleDoctor() {
49050
48617
  console.log();
49051
48618
  const passed = results.filter((r) => r.status === "pass").length;
49052
48619
  const warnings = results.filter((r) => r.status === "warn").length;
49053
- const failed3 = results.filter((r) => r.status === "fail").length;
49054
- if (failed3 > 0) {
48620
+ const failed4 = results.filter((r) => r.status === "fail").length;
48621
+ if (failed4 > 0) {
49055
48622
  console.log(
49056
- THEME2.fail(`${ICONS.fail} ${failed3} issue${failed3 === 1 ? "" : "s"} found`) + (warnings > 0 ? THEME2.warn(`, ${warnings} warning${warnings === 1 ? "" : "s"}`) : "")
48623
+ THEME2.fail(`${ICONS.fail} ${failed4} issue${failed4 === 1 ? "" : "s"} found`) + (warnings > 0 ? THEME2.warn(`, ${warnings} warning${warnings === 1 ? "" : "s"}`) : "")
49057
48624
  );
49058
48625
  console.log();
49059
48626
  console.log(THEME2.muted("Fix the issues above to ensure RelyIO works correctly."));
@@ -49083,10 +48650,10 @@ init_config();
49083
48650
  init_dashboard_url();
49084
48651
  init_manage();
49085
48652
  var THEME3 = {
49086
- success: chalk10.green,
49087
- muted: chalk10.gray,
49088
- bold: chalk10.bold,
49089
- link: chalk10.cyan.underline
48653
+ success: chalk12.green,
48654
+ muted: chalk12.gray,
48655
+ bold: chalk12.bold,
48656
+ link: chalk12.cyan.underline
49090
48657
  };
49091
48658
  function dashboard() {
49092
48659
  return requireDashboardUrl(config_default.getDashboardUrl()).replace(/\/+$/, "");
@@ -49190,11 +48757,11 @@ init_schema_loader();
49190
48757
  init_schema_validation();
49191
48758
  init_exit_codes();
49192
48759
  var THEME4 = {
49193
- success: chalk10.green,
49194
- error: chalk10.red,
49195
- warning: chalk10.yellow,
49196
- muted: chalk10.gray,
49197
- bold: chalk10.bold
48760
+ success: chalk12.green,
48761
+ error: chalk12.red,
48762
+ warning: chalk12.yellow,
48763
+ muted: chalk12.gray,
48764
+ bold: chalk12.bold
49198
48765
  };
49199
48766
  var ICONS2 = {
49200
48767
  success: "\u2713",
@@ -49206,12 +48773,15 @@ async function handleValidate(options) {
49206
48773
  const start = performance.now();
49207
48774
  let result;
49208
48775
  try {
49209
- const detection = await detectSchemaSource();
49210
- if (!detection.sourceType) throw new SchemaNotFoundError(process.cwd());
49211
48776
  result = await validateLocalSchema();
49212
48777
  } catch (error2) {
49213
48778
  if (error2 instanceof SchemaNotFoundError) {
49214
- if (json) throw fail("No schema found", "SCHEMA_NOT_FOUND");
48779
+ if (json) {
48780
+ throw fail(
48781
+ error2.yamlFiles.length > 0 ? error2.message : "No schema found",
48782
+ "SCHEMA_NOT_FOUND"
48783
+ );
48784
+ }
49215
48785
  console.log(error2.message);
49216
48786
  throw exitWith(EXIT_ERROR);
49217
48787
  }
@@ -49226,7 +48796,7 @@ async function handleValidate(options) {
49226
48796
  return out.json(output, output.success ? EXIT_OK : EXIT_ERROR);
49227
48797
  }
49228
48798
  console.log();
49229
- const sourcePath = result.sourceType === "typescript" ? result.sourcePath.replace(process.cwd() + "/", "") : `${result.sourcePath.length} YAML files`;
48799
+ const sourcePath = result.sourcePath.replace(process.cwd() + "/", "");
49230
48800
  if (result.errors.length === 0) {
49231
48801
  console.log(
49232
48802
  THEME4.success(ICONS2.success) + ` Schema valid ${THEME4.muted(`(${sourcePath})`)} ${THEME4.muted(`[${formatDuration(duration)}]`)}`
@@ -49275,7 +48845,7 @@ Examples:
49275
48845
  $ relyio validate # Validate local schema
49276
48846
  $ relyio validate --json # Output as JSON (for CI/CD)
49277
48847
 
49278
- This command validates your local schema files (TypeScript or YAML) with the
48848
+ This command validates your local TypeScript schema (relyio/schema.ts) with the
49279
48849
  checks deploy runs, without requiring authentication or connecting to the
49280
48850
  RelyIO API. It's useful for:
49281
48851
  \u2022 Pre-commit hooks
@@ -49541,13 +49111,13 @@ After adding, restart your shell or source the config file.
49541
49111
  );
49542
49112
  }
49543
49113
  var THEME5 = {
49544
- success: chalk10.green,
49545
- error: chalk10.red,
49546
- warning: chalk10.yellow,
49547
- muted: chalk10.gray,
49548
- bold: chalk10.bold,
49549
- alias: chalk10.cyan,
49550
- command: chalk10.yellow
49114
+ success: chalk12.green,
49115
+ error: chalk12.red,
49116
+ warning: chalk12.yellow,
49117
+ muted: chalk12.gray,
49118
+ bold: chalk12.bold,
49119
+ alias: chalk12.cyan,
49120
+ command: chalk12.yellow
49551
49121
  };
49552
49122
  var ALIAS_FILE = path5.join(os.homedir(), ".relyio", "aliases.json");
49553
49123
  function readAliases() {
@@ -49811,7 +49381,7 @@ function watchEventToFeed(event, previous) {
49811
49381
 
49812
49382
  // src/dev/watcher.ts
49813
49383
  init_deploy_service();
49814
- init_adaptation_plan();
49384
+ init_deploy_plan();
49815
49385
  init_schema_loader();
49816
49386
  var SandboxSchemaWatcher = class {
49817
49387
  options;
@@ -49938,7 +49508,7 @@ var SandboxSchemaWatcher = class {
49938
49508
  const branch = this.options.branchName;
49939
49509
  this.emit({
49940
49510
  type: "deploy-error",
49941
- message: `Not deployed: this change ${summarizeAdaptationPlan(plan)}. Read the plan with \`relyio diff --branch ${branch}\`; apply it with \`relyio deploy --branch ${branch}\`.`
49511
+ message: `Not deployed: this change ${summarizeDeployPlan(plan)}. Read the plan with \`relyio diff --branch ${branch}\`; apply it with \`relyio deploy --branch ${branch}\`.`
49942
49512
  });
49943
49513
  break;
49944
49514
  }
@@ -50068,12 +49638,12 @@ async function restoreArchivedIfNeeded(projectId, parentBranchId) {
50068
49638
  return;
50069
49639
  }
50070
49640
  if (!archivedBranchId) return;
50071
- console.log(chalk10.dim("\n Restoring your archived sandbox\u2026"));
49641
+ console.log(chalk12.dim("\n Restoring your archived sandbox\u2026"));
50072
49642
  try {
50073
49643
  await resumeSandbox(projectId, archivedBranchId);
50074
49644
  } catch (error2) {
50075
49645
  console.log(
50076
- chalk10.yellow(
49646
+ chalk12.yellow(
50077
49647
  ` Could not start restore (${error2 instanceof Error ? error2.message : String(error2)}); continuing.`
50078
49648
  )
50079
49649
  );
@@ -50086,14 +49656,14 @@ async function restoreArchivedIfNeeded(projectId, parentBranchId) {
50086
49656
  const sandboxes = await listSandboxes(projectId);
50087
49657
  const current = sandboxes.find((s) => s.branch.id === archivedBranchId);
50088
49658
  if (current && current.branch.state === "active") {
50089
- console.log(chalk10.green(" Sandbox restored.\n"));
49659
+ console.log(chalk12.green(" Sandbox restored.\n"));
50090
49660
  return;
50091
49661
  }
50092
49662
  } catch {
50093
49663
  }
50094
49664
  }
50095
49665
  console.log(
50096
- chalk10.yellow(
49666
+ chalk12.yellow(
50097
49667
  " Restore is still in progress; continuing \u2014 content may finish loading shortly.\n"
50098
49668
  )
50099
49669
  );
@@ -50103,21 +49673,21 @@ async function handleDev(options) {
50103
49673
  if (!preflight.ok) {
50104
49674
  console.log("");
50105
49675
  console.log(
50106
- chalk10.red(preflight.error === "auth" ? " \u2716 Not authenticated." : " \u2716 No project linked.")
49676
+ chalk12.red(preflight.error === "auth" ? " \u2716 Not authenticated." : " \u2716 No project linked.")
50107
49677
  );
50108
- console.log(chalk10.dim(` Run: ${chalk10.cyan(preflight.suggestion)}`));
49678
+ console.log(chalk12.dim(` Run: ${chalk12.cyan(preflight.suggestion)}`));
50109
49679
  console.log("");
50110
49680
  process.exit(1);
50111
49681
  }
50112
49682
  if (!process.stdin.isTTY) {
50113
49683
  console.log("");
50114
- console.log(chalk10.red(" relyio dev requires an interactive terminal."));
49684
+ console.log(chalk12.red(" relyio dev requires an interactive terminal."));
50115
49685
  console.log("");
50116
49686
  process.exit(1);
50117
49687
  }
50118
49688
  const projectId = config_default.getProjectId();
50119
49689
  if (!projectId) {
50120
- console.log(chalk10.red("\n No project linked. Run `relyio link` first.\n"));
49690
+ console.log(chalk12.red("\n No project linked. Run `relyio link` first.\n"));
50121
49691
  process.exit(1);
50122
49692
  }
50123
49693
  const permissionMode = validateMode(options.mode);
@@ -50130,9 +49700,9 @@ async function handleDev(options) {
50130
49700
  });
50131
49701
  const parent = await resolveParentBranchId(projectId, runtime.context.branchId);
50132
49702
  if (!parent) {
50133
- console.log(chalk10.red("\n Could not resolve a branch to fork the sandbox from."));
49703
+ console.log(chalk12.red("\n Could not resolve a branch to fork the sandbox from."));
50134
49704
  console.log(
50135
- chalk10.dim(
49705
+ chalk12.dim(
50136
49706
  runtime.place.branch.kind === "unavailable" ? ` RelyIO could not be reached (${runtime.place.branch.missing} unavailable). Check your connection and credentials, then try again.
50137
49707
  ` : " Create a branch first (e.g. `relyio deploy`) and try again.\n"
50138
49708
  )
@@ -50145,7 +49715,7 @@ async function handleDev(options) {
50145
49715
  sandbox = await createOrResumeSandbox(projectId, parent.id);
50146
49716
  } catch (error2) {
50147
49717
  console.log(
50148
- chalk10.red(
49718
+ chalk12.red(
50149
49719
  `
50150
49720
  Failed to provision the sandbox: ${error2 instanceof Error ? error2.message : String(error2)}
50151
49721
  `
@@ -50703,7 +50273,15 @@ async function runGitHubConnect(options, io = defaultConnectIo()) {
50703
50273
  io.log(
50704
50274
  `Bound ${bound2.repositoryFullName} (default branch ${bound2.defaultBranch}) at ${bound2.path}.`
50705
50275
  );
50706
- io.log(MODE_LINES[bound2.schemaMode]);
50276
+ if (created.exportNotOpened !== void 0) {
50277
+ io.log(
50278
+ `Main holds a deployed schema, and RelyIO could not open the Export: ${created.exportNotOpened.reason}. The project is bound in Direct mode with no move pending; ask for Repo mode again with: relyio github mode repo`
50279
+ );
50280
+ } else if (created.repoMove === void 0) {
50281
+ io.log(MODE_LINES[bound2.schemaMode]);
50282
+ } else {
50283
+ for (const line of exportLines(created.repoMove)) io.log(line);
50284
+ }
50707
50285
  return bound2;
50708
50286
  }
50709
50287
  async function runGitHubStatus(options, io) {
@@ -50739,11 +50317,25 @@ async function runGitHubMode(mode, options, io) {
50739
50317
  }
50740
50318
  const switched = await setGitHubSchemaMode(projectId, wanted);
50741
50319
  const now = modeField(switched.config);
50320
+ if (switched.repoMove !== void 0) {
50321
+ for (const line of exportLines(switched.repoMove)) io.log(line);
50322
+ return now;
50323
+ }
50742
50324
  io.log(
50743
50325
  now === "direct" ? "RelyIO writes main\u2019s schema now: relyio deploy and approved proposals reach main again." : "The repository writes main\u2019s schema now: main changes only from its CI. Other branches still take relyio deploy."
50744
50326
  );
50745
50327
  return now;
50746
50328
  }
50329
+ function exportLines(move) {
50330
+ const opened = move.export;
50331
+ return [
50332
+ opened.state === "open" ? `Main holds a deployed schema, so RelyIO opened the Export: ${opened.url} (pull request #${String(opened.number)} from ${opened.branch}).` : "Main holds a deployed schema, so RelyIO is opening the Export: one pull request from relyio/export writing it into relyio/schema.ts.",
50333
+ ...opened.state === "open" && opened.schema === "left-out" ? [
50334
+ "The repository already holds a schema source, so the Export leaves the schema out: make it declare what Production holds before merging."
50335
+ ] : [],
50336
+ "Until it merges and your default branch\u2019s relyio ci deploys the merge, the project stays in Direct mode and main takes no deploy and no approved proposal. Close the pull request without merging to cancel the move."
50337
+ ];
50338
+ }
50747
50339
  async function runGitHubDisconnect(options, io) {
50748
50340
  const projectId = await requireProject2(options.project);
50749
50341
  const connection = await findGitHubConnection(projectId);
@@ -50945,7 +50537,20 @@ function describe4(link, io) {
50945
50537
  io.log(`Connection: ${link.connectionId}`);
50946
50538
  io.log(`Environment: ${link.environment}`);
50947
50539
  io.log(`Workflow: ${link.workflowFile ?? "none (the host reports its own deployments)"}`);
50948
- io.log(`State: ${link.state}${link.reason === null ? "" : ` (${link.reason})`}`);
50540
+ io.log(`State: ${link.state}${stateDetail(link)}`);
50541
+ }
50542
+ function stateDetail(link) {
50543
+ if (link.reason !== null) return ` (${link.reason})`;
50544
+ if (link.state !== "linked" || link.waiting === null) return "";
50545
+ switch (link.waiting.reason) {
50546
+ case "pull-request-not-merged": {
50547
+ return ` \u2014 waiting for pull request #${link.pullNumber} to merge (a deployment found it open at ${link.waiting.seenAt})`;
50548
+ }
50549
+ default: {
50550
+ const unhandled = link.waiting.reason;
50551
+ return ` \u2014 waiting (${String(unhandled)})`;
50552
+ }
50553
+ }
50949
50554
  }
50950
50555
  async function runReleaseLink(releaseId, options, io) {
50951
50556
  const projectId = await requireProject2(options.project);
@@ -51209,7 +50814,7 @@ function connectionCommands(program2) {
51209
50814
  init_dist8();
51210
50815
 
51211
50816
  // ../sdk/dist/preview/index.js
51212
- init_chunk_CQHEG7QA();
50817
+ init_chunk_OVMIHAYK();
51213
50818
 
51214
50819
  // src/api/ci.ts
51215
50820
  init_dist8();
@@ -51323,7 +50928,7 @@ async function compareGeneratedTypes(schema, projectRoot) {
51323
50928
  }
51324
50929
 
51325
50930
  // src/commands/ci.ts
51326
- init_adaptation_plan();
50931
+ init_deploy_plan();
51327
50932
  init_exit_codes();
51328
50933
  init_schema_loader();
51329
50934
  var defaultIo2 = () => ({
@@ -51385,11 +50990,20 @@ function projectOf(io, named2) {
51385
50990
  }
51386
50991
  return linked;
51387
50992
  }
50993
+ var NO_WORK_FOR_THIS_JOB = /* @__PURE__ */ new Set([
50994
+ "event-not-accepted",
50995
+ "not-a-branch-push"
50996
+ ]);
50997
+ function nothingToDo(io, message) {
50998
+ annotate(io, "notice", message);
50999
+ io.log(message);
51000
+ return EXIT_OK;
51001
+ }
51388
51002
  function detailsOf(body) {
51389
51003
  const details = body?.error.details;
51390
51004
  return typeof details === "object" && details !== null ? details : {};
51391
51005
  }
51392
- async function signIn(io, options) {
51006
+ async function signIn(io, options, noWork = /* @__PURE__ */ new Set()) {
51393
51007
  const projectId = projectOf(io, options.project);
51394
51008
  const oidc = await requestGitHubOidcToken(io.env, io.fetch);
51395
51009
  if (oidc.kind === "unavailable") {
@@ -51417,6 +51031,12 @@ async function signIn(io, options) {
51417
51031
  if (body?.error.code === "RESOURCE_NOT_FOUND" && details.kind === "branch" && pushed !== void 0 && details.id === pushed) {
51418
51032
  return { kind: "nothing-to-do", message: said };
51419
51033
  }
51034
+ if (typeof details.rule === "string" && noWork.has(details.rule)) {
51035
+ return {
51036
+ kind: "nothing-to-do",
51037
+ message: `Nothing to do for this job: ${said}. \`relyio ci\` checks and previews a pull request, and deploys a push of the default branch.`
51038
+ };
51039
+ }
51420
51040
  const rule = typeof details.rule === "string" ? ` (${details.rule})` : "";
51421
51041
  return refuse3(
51422
51042
  io,
@@ -51440,19 +51060,17 @@ function targetLabel(target) {
51440
51060
  }
51441
51061
  async function runCiDeploy(options, io = defaultIo2()) {
51442
51062
  const signedIn = await signIn(io, options);
51443
- if (signedIn.kind === "nothing-to-do") {
51444
- annotate(io, "notice", signedIn.message);
51445
- io.log(signedIn.message);
51446
- return EXIT_OK;
51447
- }
51448
- const { projectId, ci } = signedIn;
51449
- const { target } = ci;
51063
+ if (signedIn.kind === "nothing-to-do") return nothingToDo(io, signedIn.message);
51064
+ const { target } = signedIn.ci;
51450
51065
  if (target.kind === "pull-request") {
51451
- const message = `This job runs for ${targetLabel(target)}, which deploys nothing; run \`relyio ci check\` on pull requests.`;
51452
- annotate(io, "notice", message);
51453
- io.log(message);
51454
- return EXIT_OK;
51066
+ return nothingToDo(
51067
+ io,
51068
+ `This job runs for ${targetLabel(target)}, which deploys nothing; run \`relyio ci check\` on pull requests.`
51069
+ );
51455
51070
  }
51071
+ return await deployPush(io, signedIn, target);
51072
+ }
51073
+ async function deployPush(io, { projectId, ci }, target) {
51456
51074
  io.log(`Signed in to RelyIO for ${targetLabel(target)}, at ${ci.sha.slice(0, 7)}.`);
51457
51075
  const result = await run({
51458
51076
  projectRoot: io.cwd,
@@ -51461,7 +51079,11 @@ async function runCiDeploy(options, io = defaultIo2()) {
51461
51079
  branchId: target.branchId,
51462
51080
  branchName: target.branchName,
51463
51081
  gitCommitSha: ci.sha
51464
- }
51082
+ },
51083
+ // While the project moves to Repo mode, the deploy of the Export's merge completes the move even
51084
+ // when nobody edited it, so main deploys an unchanged schema and Manage says whether this commit
51085
+ // is that merge (spec 0 M6, REL-3721).
51086
+ deployUnchanged: target.kind === "main" && ci.repoMovePending
51465
51087
  });
51466
51088
  return reportDeploy(io, result, ci, target.kind);
51467
51089
  }
@@ -51472,10 +51094,12 @@ function reportDeploy(io, result, ci, kind) {
51472
51094
  return EXIT_OK;
51473
51095
  }
51474
51096
  case "deployed": {
51475
- io.log(`Deployed version ${result.version} to ${result.preview.branchName}.`);
51097
+ io.log(
51098
+ `Deployed version ${result.version} to ${result.preview.branchName}: Deployment ${result.deployment.id}, plan ${result.deployment.planId}.`
51099
+ );
51476
51100
  if (result.adaptation !== void 0) {
51477
51101
  io.log(
51478
- `Plan ${result.adaptation.plan.planId} is adapting stored content in ${result.adaptation.datasets.length} dataset(s).`
51102
+ `The schema is adapting stored content in ${result.adaptation.datasets.length} dataset(s).`
51479
51103
  );
51480
51104
  }
51481
51105
  if (result.verified === "failed") {
@@ -51485,7 +51109,7 @@ function reportDeploy(io, result, ci, kind) {
51485
51109
  }
51486
51110
  case "plan-required": {
51487
51111
  const { blockage } = result;
51488
- io.log(formatAdaptationPlan(blockage.plan));
51112
+ io.log(formatDeployPlan(blockage.plan));
51489
51113
  return refuse3(io, ...planRefusal(ci, kind, blockage));
51490
51114
  }
51491
51115
  case "cancelled": {
@@ -51498,8 +51122,8 @@ function reportDeploy(io, result, ci, kind) {
51498
51122
  }
51499
51123
  function planRefusal(ci, kind, blockage) {
51500
51124
  const { plan } = blockage;
51501
- if (kind === "main" && ci.schemaMode === "repo") {
51502
- return blockage.kind === "schema-plan-stale" ? [
51125
+ if (kind === "main" && (ci.schemaMode === "repo" || ci.repoMovePending)) {
51126
+ return blockage.kind === "manifest-plan-stale" ? [
51503
51127
  `The plan the pull request confirmed (${blockage.confirmedPlanId}) is not this deploy\u2019s any more: main moved since. Nothing was deployed.`,
51504
51128
  "SCHEMA_PLAN_STALE",
51505
51129
  `The RelyIO App posted plan ${plan.planId} on the merged pull request. A maintainer with write access confirms it there with the ${GITHUB_CONFIRM_PLAN_LABEL} label; then re-run this job.`
@@ -51511,7 +51135,7 @@ function planRefusal(ci, kind, blockage) {
51511
51135
  }
51512
51136
  return [
51513
51137
  `This deploy changes stored content, and nobody can confirm plan ${plan.planId} from CI. Nothing was deployed.`,
51514
- blockage.kind === "schema-plan-stale" ? "SCHEMA_PLAN_STALE" : "SCHEMA_PLAN_UNCONFIRMED",
51138
+ blockage.kind === "manifest-plan-stale" ? "SCHEMA_PLAN_STALE" : "SCHEMA_PLAN_UNCONFIRMED",
51515
51139
  `Read the plan, then deploy it from your machine with \`relyio deploy --accept-plan ${plan.planId}\`.`
51516
51140
  ];
51517
51141
  }
@@ -51519,7 +51143,7 @@ function unconfirmedOnPullRequestFacts(facts) {
51519
51143
  if (typeof facts !== "object" || facts === null) return void 0;
51520
51144
  const { pullNumber, plan } = facts;
51521
51145
  if (pullNumber !== null && typeof pullNumber !== "number") return void 0;
51522
- return isAdaptationPlan(plan) ? { pullNumber, plan } : void 0;
51146
+ return isManifestPlan(plan) ? { pullNumber, plan } : void 0;
51523
51147
  }
51524
51148
  function reportDeployFailure(io, error2, ci, kind) {
51525
51149
  for (const issue of error2.validationErrors ?? []) {
@@ -51527,12 +51151,12 @@ function reportDeployFailure(io, error2, ci, kind) {
51527
51151
  }
51528
51152
  const blockage = detailsOf(error2.refusal).blockage;
51529
51153
  switch (blockage?.kind) {
51530
- case "schema-plan-unconfirmed-on-pull-request": {
51154
+ case "manifest-plan-unconfirmed-on-pull-request": {
51531
51155
  const facts = unconfirmedOnPullRequestFacts(blockage.facts);
51532
51156
  if (facts === void 0) {
51533
51157
  return refuse3(io, error2.message, error2.code ?? "DEPLOY_FAILED");
51534
51158
  }
51535
- io.log(formatAdaptationPlan(facts.plan));
51159
+ io.log(formatDeployPlan(facts.plan));
51536
51160
  return refuse3(
51537
51161
  io,
51538
51162
  error2.message,
@@ -51554,19 +51178,17 @@ function reportDeployFailure(io, error2, ci, kind) {
51554
51178
  }
51555
51179
  async function runCiCheck(options, io = defaultIo2()) {
51556
51180
  const signedIn = await signIn(io, options);
51557
- if (signedIn.kind === "nothing-to-do") {
51558
- annotate(io, "notice", signedIn.message);
51559
- io.log(signedIn.message);
51560
- return EXIT_OK;
51561
- }
51562
- const { projectId, ci } = signedIn;
51563
- const { target } = ci;
51181
+ if (signedIn.kind === "nothing-to-do") return nothingToDo(io, signedIn.message);
51182
+ const { target } = signedIn.ci;
51564
51183
  if (target.kind !== "pull-request") {
51565
- const message = `This job is a push to ${targetLabel(target)}, which \`relyio ci deploy\` deploys; a schema check runs on a pull request.`;
51566
- annotate(io, "notice", message);
51567
- io.log(message);
51568
- return EXIT_OK;
51184
+ return nothingToDo(
51185
+ io,
51186
+ `This job is a push to ${targetLabel(target)}, which \`relyio ci deploy\` deploys; a schema check runs on a pull request.`
51187
+ );
51569
51188
  }
51189
+ return await checkPullRequest(io, signedIn);
51190
+ }
51191
+ async function checkPullRequest(io, { projectId, ci }) {
51570
51192
  let loaded;
51571
51193
  try {
51572
51194
  loaded = await loadSchema(io.cwd);
@@ -51608,25 +51230,23 @@ async function runCiCheck(options, io = defaultIo2()) {
51608
51230
  `Submitted the schema check for pull request #${answer.pullNumber} at ${answer.headSha.slice(0, 7)}: ${answer.conclusion}.`
51609
51231
  );
51610
51232
  io.log(
51611
- `The RelyIO GitHub App posts it as \u201C${GITHUB_SCHEMA_CHECK_NAME}\u201D; that check run is the verdict, not this job.`
51233
+ `The RelyIO GitHub App posts it as \u201C${GITHUB_PLAN_CHECK_NAME}\u201D; that check run is the verdict, not this job.`
51612
51234
  );
51613
51235
  return EXIT_OK;
51614
51236
  }
51615
51237
  async function runCiPreview(options, io = defaultIo2()) {
51616
51238
  const signedIn = await signIn(io, options);
51617
- if (signedIn.kind === "nothing-to-do") {
51618
- annotate(io, "notice", signedIn.message);
51619
- io.log(signedIn.message);
51620
- return EXIT_OK;
51621
- }
51622
- const { projectId, ci } = signedIn;
51623
- const { target } = ci;
51239
+ if (signedIn.kind === "nothing-to-do") return nothingToDo(io, signedIn.message);
51240
+ const { target } = signedIn.ci;
51624
51241
  if (target.kind !== "pull-request") {
51625
- const message = `This job is a push to ${targetLabel(target)}, which \`relyio ci deploy\` deploys; a preview is a pull request\u2019s.`;
51626
- annotate(io, "notice", message);
51627
- io.log(message);
51628
- return EXIT_OK;
51242
+ return nothingToDo(
51243
+ io,
51244
+ `This job is a push to ${targetLabel(target)}, which \`relyio ci deploy\` deploys; a preview is a pull request\u2019s.`
51245
+ );
51629
51246
  }
51247
+ return await previewPullRequest(io, signedIn, target);
51248
+ }
51249
+ async function previewPullRequest(io, { projectId, ci }, target) {
51630
51250
  const datasetName = previewDatasetSlug(target.headRef);
51631
51251
  let answer;
51632
51252
  try {
@@ -51672,36 +51292,62 @@ async function runCiPreview(options, io = defaultIo2()) {
51672
51292
  }) : prepared.result;
51673
51293
  return reportDeploy(io, result, ci, "branch");
51674
51294
  }
51295
+ async function runCi(options, io = defaultIo2()) {
51296
+ const signedIn = await signIn(io, options, NO_WORK_FOR_THIS_JOB);
51297
+ if (signedIn.kind === "nothing-to-do") return nothingToDo(io, signedIn.message);
51298
+ const { target } = signedIn.ci;
51299
+ switch (target.kind) {
51300
+ case "pull-request": {
51301
+ await checkPullRequest(io, signedIn);
51302
+ return await previewPullRequest(io, signedIn, target);
51303
+ }
51304
+ case "main": {
51305
+ return await deployPush(io, signedIn, target);
51306
+ }
51307
+ case "branch": {
51308
+ return nothingToDo(
51309
+ io,
51310
+ `This job is a push to ${targetLabel(target)}, and \`relyio ci\` deploys only a push of the default branch; run \`relyio ci deploy\` to deploy ${target.branchName} from its pushes.`
51311
+ );
51312
+ }
51313
+ }
51314
+ }
51675
51315
  var PROJECT_OPTION4 = {
51676
51316
  flags: "--project <project>",
51677
51317
  description: "The project id (default: the project linked in this directory)"
51678
51318
  };
51679
51319
  function ciCommands(program2) {
51680
- const ci = defineGroup(
51681
- program2,
51682
- "ci",
51683
- "Deploy, check or preview the schema from a GitHub Actions job, signed in with its OIDC token"
51684
- );
51320
+ const ci = defineCommand(program2, {
51321
+ name: "ci",
51322
+ description: "Run RelyIO from a GitHub Actions job, signed in with its OIDC token: with no subcommand, check and preview a pull request, or deploy a push of the default branch",
51323
+ auth: false,
51324
+ options: [PROJECT_OPTION4],
51325
+ handler: async (options) => await runCi(options)
51326
+ });
51327
+ const withProject = (options) => ({
51328
+ ...ci.opts(),
51329
+ ...options.project === void 0 ? {} : { project: options.project }
51330
+ });
51685
51331
  defineCommand(ci, {
51686
51332
  name: "deploy",
51687
51333
  description: "Deploy the schema to what this job\u2019s ref names: main on a push of the default branch, else the branch of that name",
51688
51334
  auth: false,
51689
51335
  options: [PROJECT_OPTION4],
51690
- handler: async (options) => await runCiDeploy(options)
51336
+ handler: async (options) => await runCiDeploy(withProject(options))
51691
51337
  });
51692
51338
  defineCommand(ci, {
51693
51339
  name: "check",
51694
51340
  description: "Submit this pull request\u2019s schema; the RelyIO GitHub App posts the plan as the check run",
51695
51341
  auth: false,
51696
51342
  options: [PROJECT_OPTION4],
51697
- handler: async (options) => await runCiCheck(options)
51343
+ handler: async (options) => await runCiCheck(withProject(options))
51698
51344
  });
51699
51345
  defineCommand(ci, {
51700
51346
  name: "preview",
51701
51347
  description: "Create or update this pull request\u2019s preview \u2014 a branch whose dataset links to the base\u2019s \u2014 and deploy the schema to it",
51702
51348
  auth: false,
51703
51349
  options: [PROJECT_OPTION4],
51704
- handler: async (options) => await runCiPreview(options)
51350
+ handler: async (options) => await runCiPreview(withProject(options))
51705
51351
  });
51706
51352
  }
51707
51353
  init_config();
@@ -51797,11 +51443,11 @@ async function handleAI(options) {
51797
51443
  if (!preflight.ok) {
51798
51444
  console.log("");
51799
51445
  if (preflight.error === "auth") {
51800
- console.log(chalk10.red(" \u2716 Not authenticated."));
51446
+ console.log(chalk12.red(" \u2716 Not authenticated."));
51801
51447
  } else {
51802
- console.log(chalk10.red(" \u2716 No project linked."));
51448
+ console.log(chalk12.red(" \u2716 No project linked."));
51803
51449
  }
51804
- console.log(chalk10.dim(` Run: ${chalk10.cyan(preflight.suggestion)}`));
51450
+ console.log(chalk12.dim(` Run: ${chalk12.cyan(preflight.suggestion)}`));
51805
51451
  console.log("");
51806
51452
  process.exit(1);
51807
51453
  }
@@ -51812,8 +51458,8 @@ async function handleAI(options) {
51812
51458
  }
51813
51459
  if (!process.stdin.isTTY && !options.json) {
51814
51460
  console.log("");
51815
- console.log(chalk10.red(" relyio ai requires an interactive terminal."));
51816
- console.log(chalk10.dim(" Use --json for non-interactive output, or run in a TTY."));
51461
+ console.log(chalk12.red(" relyio ai requires an interactive terminal."));
51462
+ console.log(chalk12.dim(" Use --json for non-interactive output, or run in a TTY."));
51817
51463
  console.log("");
51818
51464
  process.exit(1);
51819
51465
  }
@@ -51944,11 +51590,11 @@ function printResumeHint(serverConversationId, sessionManager) {
51944
51590
  const suffix = serverConversationId.slice(-8);
51945
51591
  console.log("");
51946
51592
  if (title) {
51947
- console.log(chalk10.dim(` ${chalk10.cyan("\u25B6")} Conversation saved \u2014 ${chalk10.white(title)}`));
51593
+ console.log(chalk12.dim(` ${chalk12.cyan("\u25B6")} Conversation saved \u2014 ${chalk12.white(title)}`));
51948
51594
  } else {
51949
- console.log(chalk10.dim(` ${chalk10.cyan("\u25B6")} Conversation saved.`));
51595
+ console.log(chalk12.dim(` ${chalk12.cyan("\u25B6")} Conversation saved.`));
51950
51596
  }
51951
- console.log(chalk10.dim(` Resume any time: ${chalk10.cyan(`relyio ai -r ${suffix}`)}`));
51597
+ console.log(chalk12.dim(` Resume any time: ${chalk12.cyan(`relyio ai -r ${suffix}`)}`));
51952
51598
  console.log("");
51953
51599
  }
51954
51600
  function validateMode2(mode) {
@@ -51957,7 +51603,7 @@ function validateMode2(mode) {
51957
51603
  if (valid2.includes(mode)) {
51958
51604
  return mode;
51959
51605
  }
51960
- console.log(chalk10.yellow(` Warning: Unknown mode "${mode}". Using "safe".`));
51606
+ console.log(chalk12.yellow(` Warning: Unknown mode "${mode}". Using "safe".`));
51961
51607
  return "safe";
51962
51608
  }
51963
51609
  async function resolveModelFlag(rawRef) {
@@ -51965,15 +51611,15 @@ async function resolveModelFlag(rawRef) {
51965
51611
  const catalog = await getModelsClient().listModels();
51966
51612
  const match = resolveModelRef(catalog, rawRef);
51967
51613
  if (!match) {
51968
- console.log(chalk10.red(`
51614
+ console.log(chalk12.red(`
51969
51615
  Unknown model "${rawRef}".`));
51970
- console.log(chalk10.dim(` Available: ${catalog.map((m) => m.id).join(", ")}`));
51971
- console.log(chalk10.dim(" Aliases: auto, sonnet, haiku, gpt-5.2, gpt-5\n"));
51616
+ console.log(chalk12.dim(` Available: ${catalog.map((m) => m.id).join(", ")}`));
51617
+ console.log(chalk12.dim(" Aliases: auto, sonnet, haiku, gpt-5.2, gpt-5\n"));
51972
51618
  return "invalid";
51973
51619
  }
51974
51620
  if (!match.available) {
51975
51621
  console.log(
51976
- chalk10.red(
51622
+ chalk12.red(
51977
51623
  `
51978
51624
  Cannot use ${match.name} \u2014 this model is currently disabled by the workspace admin.
51979
51625
  `
@@ -51984,13 +51630,13 @@ async function resolveModelFlag(rawRef) {
51984
51630
  return match.id;
51985
51631
  } catch (error2) {
51986
51632
  console.log(
51987
- chalk10.yellow(
51633
+ chalk12.yellow(
51988
51634
  `
51989
51635
  Could not reach the gateway to validate --model: ` + (error2 instanceof Error ? error2.message : String(error2))
51990
51636
  )
51991
51637
  );
51992
51638
  console.log(
51993
- chalk10.dim(" Booting with the value as-is; the gateway will validate on first turn.\n")
51639
+ chalk12.dim(" Booting with the value as-is; the gateway will validate on first turn.\n")
51994
51640
  );
51995
51641
  return rawRef;
51996
51642
  }
@@ -51998,8 +51644,8 @@ async function resolveModelFlag(rawRef) {
51998
51644
  async function listSessions() {
51999
51645
  const projectId = config_default.getProjectId();
52000
51646
  if (!projectId) {
52001
- console.log(chalk10.red("\n No project linked."));
52002
- console.log(chalk10.dim(" Run: relyio link to pick a project before listing sessions.\n"));
51647
+ console.log(chalk12.red("\n No project linked."));
51648
+ console.log(chalk12.dim(" Run: relyio link to pick a project before listing sessions.\n"));
52003
51649
  return;
52004
51650
  }
52005
51651
  let conversations = [];
@@ -52014,7 +51660,7 @@ async function listSessions() {
52014
51660
  fellBackToLocal = true;
52015
51661
  if (debugEnabled()) {
52016
51662
  console.error(
52017
- chalk10.dim(
51663
+ chalk12.dim(
52018
51664
  ` [debug] gateway list failed: ${error2 instanceof Error ? error2.message : String(error2)}`
52019
51665
  )
52020
51666
  );
@@ -52023,7 +51669,7 @@ async function listSessions() {
52023
51669
  if (fellBackToLocal) {
52024
51670
  const local = new SessionManager().listRecent(20);
52025
51671
  if (local.length === 0) {
52026
- console.log(chalk10.dim("\n No saved sessions found (and the gateway is unreachable).\n"));
51672
+ console.log(chalk12.dim("\n No saved sessions found (and the gateway is unreachable).\n"));
52027
51673
  return;
52028
51674
  }
52029
51675
  renderSessionsTable(
@@ -52038,7 +51684,7 @@ async function listSessions() {
52038
51684
  return;
52039
51685
  }
52040
51686
  if (conversations.length === 0) {
52041
- console.log(chalk10.dim("\n No CLI conversations yet. Start one with `relyio ai`.\n"));
51687
+ console.log(chalk12.dim("\n No CLI conversations yet. Start one with `relyio ai`.\n"));
52042
51688
  return;
52043
51689
  }
52044
51690
  renderSessionsTable(
@@ -52061,26 +51707,26 @@ function renderSessionsTable(rows, opts = {}) {
52061
51707
  const header = " " + padCell("Title", titleWidth) + " ".repeat(COL_GAP) + padCell("ID", ID_WIDTH) + " ".repeat(COL_GAP) + padCell("Msgs", MSGS_WIDTH, "right") + " ".repeat(COL_GAP) + padCell("Updated", DATE_WIDTH);
52062
51708
  console.log("");
52063
51709
  console.log(
52064
- chalk10.bold(" Recent AI Sessions") + (opts.offline ? chalk10.dim(" (offline cache)") : "")
51710
+ chalk12.bold(" Recent AI Sessions") + (opts.offline ? chalk12.dim(" (offline cache)") : "")
52065
51711
  );
52066
51712
  console.log("");
52067
- console.log(chalk10.dim(header));
52068
- console.log(chalk10.dim(" " + "\u2500".repeat(header.length - 2)));
51713
+ console.log(chalk12.dim(header));
51714
+ console.log(chalk12.dim(" " + "\u2500".repeat(header.length - 2)));
52069
51715
  for (const row of rows) {
52070
51716
  const titleRaw = row.title.trim();
52071
51717
  const hasTitle = titleRaw.length > 0;
52072
51718
  const titleText = hasTitle ? truncate(titleRaw, titleWidth) : "(untitled)";
52073
51719
  const titleCell = padCell(titleText, titleWidth);
52074
- const titleColored = hasTitle ? chalk10.cyan(titleCell) : chalk10.dim(titleCell);
52075
- const idCell = chalk10.dim(padCell(`#${row.id.slice(-8)}`, ID_WIDTH));
52076
- const msgsCell = chalk10.dim(padCell(String(row.messageCount), MSGS_WIDTH, "right"));
52077
- const dateCell = chalk10.dim(padCell(formatRelativeDate(row.updatedAt), DATE_WIDTH));
51720
+ const titleColored = hasTitle ? chalk12.cyan(titleCell) : chalk12.dim(titleCell);
51721
+ const idCell = chalk12.dim(padCell(`#${row.id.slice(-8)}`, ID_WIDTH));
51722
+ const msgsCell = chalk12.dim(padCell(String(row.messageCount), MSGS_WIDTH, "right"));
51723
+ const dateCell = chalk12.dim(padCell(formatRelativeDate(row.updatedAt), DATE_WIDTH));
52078
51724
  console.log(
52079
51725
  " " + titleColored + " ".repeat(COL_GAP) + idCell + " ".repeat(COL_GAP) + msgsCell + " ".repeat(COL_GAP) + dateCell
52080
51726
  );
52081
51727
  }
52082
51728
  console.log("");
52083
- console.log(chalk10.dim(" Resume with: relyio ai -r <id-suffix>"));
51729
+ console.log(chalk12.dim(" Resume with: relyio ai -r <id-suffix>"));
52084
51730
  console.log("");
52085
51731
  }
52086
51732
  function padCell(str, width, align = "left") {
@@ -52124,13 +51770,13 @@ async function resolveContinue(sessionManager) {
52124
51770
  return local2;
52125
51771
  }
52126
51772
  console.log(
52127
- chalk10.yellow(
51773
+ chalk12.yellow(
52128
51774
  `
52129
- Most recent server session ${chalk10.dim(`#${newest.id.slice(-8)}`)} has no local cache on this machine.`
51775
+ Most recent server session ${chalk12.dim(`#${newest.id.slice(-8)}`)} has no local cache on this machine.`
52130
51776
  )
52131
51777
  );
52132
51778
  console.log(
52133
- chalk10.dim(
51779
+ chalk12.dim(
52134
51780
  " Starting a fresh session linked to it \u2014 older messages remain on the server.\n"
52135
51781
  )
52136
51782
  );
@@ -52141,7 +51787,7 @@ async function resolveContinue(sessionManager) {
52141
51787
  }
52142
51788
  const local = sessionManager.getMostRecent();
52143
51789
  if (!local) {
52144
- console.log(chalk10.dim("\n No recent session found. Starting fresh.\n"));
51790
+ console.log(chalk12.dim("\n No recent session found. Starting fresh.\n"));
52145
51791
  }
52146
51792
  return local;
52147
51793
  }
@@ -52237,13 +51883,13 @@ async function resolveResumeRef(sessionManager, ref) {
52237
51883
  return local;
52238
51884
  }
52239
51885
  console.log(
52240
- chalk10.yellow(
51886
+ chalk12.yellow(
52241
51887
  `
52242
- Conversation ${chalk10.dim(`#${serverMatch.id.slice(-8)}`)} has no local cache on this machine.`
51888
+ Conversation ${chalk12.dim(`#${serverMatch.id.slice(-8)}`)} has no local cache on this machine.`
52243
51889
  )
52244
51890
  );
52245
51891
  console.log(
52246
- chalk10.dim(" Starting a fresh session linked to it \u2014 older messages remain on the server.\n")
51892
+ chalk12.dim(" Starting a fresh session linked to it \u2014 older messages remain on the server.\n")
52247
51893
  );
52248
51894
  return buildCrossMachineStub(serverMatch, projectId);
52249
51895
  }
@@ -52251,31 +51897,31 @@ async function resolveResumeRef(sessionManager, ref) {
52251
51897
  if (localMatch) {
52252
51898
  if (serverReachable) {
52253
51899
  console.log(
52254
- chalk10.yellow(
51900
+ chalk12.yellow(
52255
51901
  `
52256
- Conversation ${chalk10.dim(`#${ref}`)} isn't on the configured gateway \u2014 using local cache.`
51902
+ Conversation ${chalk12.dim(`#${ref}`)} isn't on the configured gateway \u2014 using local cache.`
52257
51903
  )
52258
51904
  );
52259
51905
  console.log(
52260
- chalk10.dim(
51906
+ chalk12.dim(
52261
51907
  " Cached title may be stale. Tip: if you started this session with `RELYIO_API_URL=\u2026`,"
52262
51908
  )
52263
51909
  );
52264
- console.log(chalk10.dim(" resume with the same env so list / resume hit the same backend.\n"));
51910
+ console.log(chalk12.dim(" resume with the same env so list / resume hit the same backend.\n"));
52265
51911
  }
52266
51912
  return localMatch;
52267
51913
  }
52268
- console.log(chalk10.red(`
51914
+ console.log(chalk12.red(`
52269
51915
  No conversation matching "${ref}" found.
52270
51916
  `));
52271
51917
  if (!isValidUuid(ref)) {
52272
51918
  const serverCollisions = findAllConversationsByRef(serverConversations, ref);
52273
51919
  if (serverCollisions.length > 1) {
52274
- console.log(chalk10.dim(" Multiple suffixes matched \u2014 pass a longer suffix or a full UUID:"));
51920
+ console.log(chalk12.dim(" Multiple suffixes matched \u2014 pass a longer suffix or a full UUID:"));
52275
51921
  for (const c of serverCollisions.slice(0, 5)) {
52276
51922
  const title = c.title || "(untitled)";
52277
51923
  console.log(
52278
- chalk10.dim(
51924
+ chalk12.dim(
52279
51925
  ` relyio ai -r ${c.id.slice(-12)} ${title} (${new Date(c.updatedAt).toLocaleString()})`
52280
51926
  )
52281
51927
  );
@@ -52284,7 +51930,7 @@ async function resolveResumeRef(sessionManager, ref) {
52284
51930
  return null;
52285
51931
  }
52286
51932
  }
52287
- console.log(chalk10.dim(" Use: relyio ai --list to see available sessions"));
51933
+ console.log(chalk12.dim(" Use: relyio ai --list to see available sessions"));
52288
51934
  return null;
52289
51935
  }
52290
51936
  function aiCommand(program2) {
@@ -52327,7 +51973,7 @@ Commands inside the REPL:
52327
51973
  );
52328
51974
  }
52329
51975
  init_deploy_service();
52330
- init_adaptation_plan();
51976
+ init_deploy_plan();
52331
51977
 
52332
51978
  // src/ai/oneshot/runtime-bootstrap.ts
52333
51979
  init_runtime();
@@ -52349,17 +51995,17 @@ init_exit_codes();
52349
51995
  async function handleSchema(message, options) {
52350
51996
  const trimmed = (message ?? "").trim();
52351
51997
  if (!trimmed) {
52352
- console.log(chalk10.red(" \u2716 Provide a natural-language schema instruction."));
52353
- console.log(chalk10.dim(' Example: relyio schema "add a tags field to blogPost"'));
51998
+ console.log(chalk12.red(" \u2716 Provide a natural-language schema instruction."));
51999
+ console.log(chalk12.dim(' Example: relyio schema "add a tags field to blogPost"'));
52354
52000
  process.exit(EXIT_ERROR);
52355
52001
  }
52356
52002
  const preflight = runPreflight();
52357
52003
  if (!preflight.ok) {
52358
52004
  console.log("");
52359
52005
  console.log(
52360
- chalk10.red(preflight.error === "auth" ? " \u2716 Not authenticated." : " \u2716 No project linked.")
52006
+ chalk12.red(preflight.error === "auth" ? " \u2716 Not authenticated." : " \u2716 No project linked.")
52361
52007
  );
52362
- console.log(chalk10.dim(` Run: ${chalk10.cyan(preflight.suggestion)}`));
52008
+ console.log(chalk12.dim(` Run: ${chalk12.cyan(preflight.suggestion)}`));
52363
52009
  process.exit(EXIT_ERROR);
52364
52010
  }
52365
52011
  const permissionMode = options.dryRun ? "plan" : options.noConfirm ? "auto" : "safe";
@@ -52379,35 +52025,35 @@ async function handleSchema(message, options) {
52379
52025
  });
52380
52026
  if (exitCode === EXIT_OK && options.deploy) {
52381
52027
  console.log("");
52382
- console.log(chalk10.cyan("\u25B8 Running relyio deploy\u2026"));
52028
+ console.log(chalk12.cyan("\u25B8 Running relyio deploy\u2026"));
52383
52029
  const deployResult = await run({
52384
52030
  projectRoot: runtime.fileManifest.projectRoot,
52385
52031
  ...options.branch ? { branchName: options.branch } : {}
52386
52032
  });
52387
52033
  if (deployResult.status === "failed") {
52388
- console.log(chalk10.red(` \u2716 Deploy failed: ${deployResult.error.message}`));
52034
+ console.log(chalk12.red(` \u2716 Deploy failed: ${deployResult.error.message}`));
52389
52035
  process.exit(EXIT_BLOCKED);
52390
52036
  }
52391
52037
  if (deployResult.status === "cancelled") {
52392
- console.log(chalk10.yellow(` \u26A0 Deploy cancelled (${deployResult.reason}).`));
52038
+ console.log(chalk12.yellow(` \u26A0 Deploy cancelled (${deployResult.reason}).`));
52393
52039
  process.exit(EXIT_OK);
52394
52040
  }
52395
52041
  if (deployResult.status === "plan-required") {
52396
52042
  const { plan } = deployResult.blockage;
52397
- console.log(chalk10.yellow(" \u26A0 Not deployed: this deploy changes stored content."));
52398
- console.log(formatAdaptationPlan(plan));
52043
+ console.log(chalk12.yellow(" \u26A0 Not deployed: this deploy changes stored content."));
52044
+ console.log(formatDeployPlan(plan));
52399
52045
  console.log(
52400
- chalk10.dim(
52046
+ chalk12.dim(
52401
52047
  ` Apply it with \`relyio deploy\` (answering yes) or \`relyio deploy --accept-plan ${plan.planId}\`.`
52402
52048
  )
52403
52049
  );
52404
52050
  process.exit(EXIT_BLOCKED);
52405
52051
  }
52406
52052
  if (deployResult.status === "no-changes") {
52407
- console.log(chalk10.dim(" No changes to deploy."));
52053
+ console.log(chalk12.dim(" No changes to deploy."));
52408
52054
  } else if (deployResult.status === "deployed") {
52409
52055
  console.log(
52410
- chalk10.green(
52056
+ chalk12.green(
52411
52057
  ` \u2713 Deployed ${deployResult.preview.branchName} (v${deployResult.version}) in ${deployResult.durationMs}ms`
52412
52058
  )
52413
52059
  );
@@ -52470,17 +52116,17 @@ init_exit_codes();
52470
52116
  async function handleDraft(message, options) {
52471
52117
  const trimmed = (message ?? "").trim();
52472
52118
  if (!trimmed) {
52473
- console.log(chalk10.red(" \u2716 Provide a natural-language drafting instruction."));
52474
- console.log(chalk10.dim(' Example: relyio draft "create 5 blog posts about AI"'));
52119
+ console.log(chalk12.red(" \u2716 Provide a natural-language drafting instruction."));
52120
+ console.log(chalk12.dim(' Example: relyio draft "create 5 blog posts about AI"'));
52475
52121
  process.exit(EXIT_ERROR);
52476
52122
  }
52477
52123
  const preflight = runPreflight();
52478
52124
  if (!preflight.ok) {
52479
52125
  console.log("");
52480
52126
  console.log(
52481
- chalk10.red(preflight.error === "auth" ? " \u2716 Not authenticated." : " \u2716 No project linked.")
52127
+ chalk12.red(preflight.error === "auth" ? " \u2716 Not authenticated." : " \u2716 No project linked.")
52482
52128
  );
52483
- console.log(chalk10.dim(` Run: ${chalk10.cyan(preflight.suggestion)}`));
52129
+ console.log(chalk12.dim(` Run: ${chalk12.cyan(preflight.suggestion)}`));
52484
52130
  process.exit(EXIT_ERROR);
52485
52131
  }
52486
52132
  const permissionMode = options.noConfirm ? "auto" : "safe";
@@ -52763,17 +52409,17 @@ var VALID_FORMATS = ["table", "json", "csv", "count"];
52763
52409
  async function handleQuery(message, options) {
52764
52410
  const trimmed = (message ?? "").trim();
52765
52411
  if (!trimmed) {
52766
- console.log(chalk10.red(" \u2716 Provide a natural-language question."));
52767
- console.log(chalk10.dim(' Example: relyio query "all published blog posts"'));
52412
+ console.log(chalk12.red(" \u2716 Provide a natural-language question."));
52413
+ console.log(chalk12.dim(' Example: relyio query "all published blog posts"'));
52768
52414
  process.exit(EXIT_ERROR);
52769
52415
  }
52770
52416
  const preflight = runPreflight();
52771
52417
  if (!preflight.ok) {
52772
52418
  console.log("");
52773
52419
  console.log(
52774
- chalk10.red(preflight.error === "auth" ? " \u2716 Not authenticated." : " \u2716 No project linked.")
52420
+ chalk12.red(preflight.error === "auth" ? " \u2716 Not authenticated." : " \u2716 No project linked.")
52775
52421
  );
52776
- console.log(chalk10.dim(` Run: ${chalk10.cyan(preflight.suggestion)}`));
52422
+ console.log(chalk12.dim(` Run: ${chalk12.cyan(preflight.suggestion)}`));
52777
52423
  process.exit(EXIT_ERROR);
52778
52424
  }
52779
52425
  const format2 = parseFormat(options.format);
@@ -52861,7 +52507,7 @@ async function mountAndWait3(args) {
52861
52507
  function parseFormat(raw) {
52862
52508
  if (!raw) return "table";
52863
52509
  if (VALID_FORMATS.includes(raw)) return raw;
52864
- console.log(chalk10.yellow(` Warning: unknown format "${raw}". Falling back to "table".`));
52510
+ console.log(chalk12.yellow(` Warning: unknown format "${raw}". Falling back to "table".`));
52865
52511
  return "table";
52866
52512
  }
52867
52513
  function parseLimit(raw) {
@@ -52894,7 +52540,7 @@ Examples:
52894
52540
  }
52895
52541
 
52896
52542
  // src/index.ts
52897
- var CLI_VERSION3 = "0.11.0" ;
52543
+ var CLI_VERSION3 = "0.12.0" ;
52898
52544
  var program = new Command();
52899
52545
  program.name("relyio").description("RelyIO CLI - Content Management, Simplified").version(CLI_VERSION3);
52900
52546
  registerGlobalOptions(program);
@@ -52903,6 +52549,7 @@ loginCommand(program);
52903
52549
  logoutCommand(program);
52904
52550
  deployCommand(program);
52905
52551
  diffCommand(program);
52552
+ planCommand(program);
52906
52553
  doctorCommand(program);
52907
52554
  openCommand(program);
52908
52555
  validateCommand(program);