@anvil-works/anvil-cli 0.5.15 → 0.6.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
@@ -31356,13 +31356,17 @@ var __webpack_exports__ = {};
31356
31356
  validateAnvilApp: ()=>validation_validateAnvilApp,
31357
31357
  getGitPushUrl: ()=>anvil_api_getGitPushUrl,
31358
31358
  ValidateAppIdResponse: ()=>anvil_api_namespaceObject.ValidateAppIdResponse,
31359
+ formatValidationPath: ()=>formatValidationPath,
31359
31360
  resolveAnvilUrl: ()=>resolveAnvilUrl,
31360
31361
  parseCheckoutInput: ()=>parseCheckoutInput,
31361
31362
  login: ()=>login,
31362
31363
  resetConfig: ()=>resetConfig,
31363
31364
  resolveCheckoutUsername: ()=>resolveCheckoutUsername,
31364
31365
  detectAppIdsByCommitLookup: ()=>anvil_api_detectAppIdsByCommitLookup,
31366
+ FormTemplateValidationResult: ()=>validators_namespaceObject.FormTemplateValidationResult,
31367
+ ValidationTarget: ()=>validators_namespaceObject.ValidationTarget,
31365
31368
  sanitizeDirectoryName: ()=>sanitizeDirectoryName,
31369
+ validatePath: ()=>validatePath,
31366
31370
  LoginResult: ()=>auth_namespaceObject.LoginResult,
31367
31371
  listAppsForCheckout: ()=>listAppsForCheckout,
31368
31372
  getInstalledPreferredEditors: ()=>getInstalledPreferredEditors,
@@ -31380,7 +31384,9 @@ var __webpack_exports__ = {};
31380
31384
  ensureCheckoutAuthToken: ()=>ensureCheckoutAuthToken,
31381
31385
  isPathInsideGitRepo: ()=>isPathInsideGitRepo,
31382
31386
  normalizeAnvilUrl: ()=>config_normalizeAnvilUrl,
31387
+ ValidationIssue: ()=>validators_namespaceObject.ValidationIssue,
31383
31388
  getTokensForUrl: ()=>getTokensForUrl,
31389
+ validateFormTemplate: ()=>validateFormTemplate,
31384
31390
  preferredEditors: ()=>preferredEditors,
31385
31391
  LogoutResult: ()=>auth_namespaceObject.LogoutResult,
31386
31392
  getPreferredEditorCommand: ()=>config_getPreferredEditorCommand,
@@ -31390,6 +31396,8 @@ var __webpack_exports__ = {};
31390
31396
  validateBranchSyncStatus: ()=>validation_validateBranchSyncStatus,
31391
31397
  checkUncommittedChanges: ()=>api_checkUncommittedChanges,
31392
31398
  hasTokensForUrl: ()=>auth_hasTokensForUrl,
31399
+ AnvilYamlValidationResult: ()=>validators_namespaceObject.AnvilYamlValidationResult,
31400
+ ValidatePathResult: ()=>validators_namespaceObject.ValidatePathResult,
31393
31401
  getSettableConfigKeys: ()=>getSettableConfigKeys,
31394
31402
  logout: ()=>logout,
31395
31403
  TokenData: ()=>auth_namespaceObject.TokenData,
@@ -31406,6 +31414,7 @@ var __webpack_exports__ = {};
31406
31414
  resolveCheckoutUrl: ()=>resolveCheckoutUrl,
31407
31415
  PreferredEditor: ()=>config_namespaceObject.PreferredEditor,
31408
31416
  getAvailableAnvilUrls: ()=>getAvailableAnvilUrls,
31417
+ validateAnvilYaml: ()=>validateAnvilYaml,
31409
31418
  CheckoutCloneOptions: ()=>checkout_namespaceObject.CheckoutCloneOptions,
31410
31419
  formatCandidateLabel: ()=>anvil_api_formatCandidateLabel,
31411
31420
  StoredTokens: ()=>auth_namespaceObject.StoredTokens,
@@ -31463,6 +31472,14 @@ var __webpack_exports__ = {};
31463
31472
  Us: ()=>saveUpdates,
31464
31473
  zW: ()=>anvil_api_validateAppId
31465
31474
  });
31475
+ var validators_namespaceObject = {};
31476
+ __webpack_require__.r(validators_namespaceObject);
31477
+ __webpack_require__.d(validators_namespaceObject, {
31478
+ k_: ()=>formatValidationPath,
31479
+ Yr: ()=>validateAnvilYaml,
31480
+ hb: ()=>validateFormTemplate,
31481
+ iQ: ()=>validatePath
31482
+ });
31466
31483
  var validation_namespaceObject = {};
31467
31484
  __webpack_require__.r(validation_namespaceObject);
31468
31485
  __webpack_require__.d(validation_namespaceObject, {
@@ -36077,6 +36094,7 @@ var __webpack_exports__ = {};
36077
36094
  init_git_response_error();
36078
36095
  var esm_default = gitInstanceFactory;
36079
36096
  var external_fs_ = __webpack_require__("fs");
36097
+ var external_fs_default = /*#__PURE__*/ __webpack_require__.n(external_fs_);
36080
36098
  /*! js-yaml 4.1.1 https://github.com/nodeca/js-yaml @license MIT */ function isNothing(subject) {
36081
36099
  return null == subject;
36082
36100
  }
@@ -39412,18 +39430,27 @@ var __webpack_exports__ = {};
39412
39430
  if (list.length > 1) return `(${list.join(` ${separator} `)})`;
39413
39431
  return list[0] ?? "never";
39414
39432
  }
39415
- function minValue(requirement, message$1) {
39433
+ function getDotPath(issue) {
39434
+ if (issue.path) {
39435
+ let key = "";
39436
+ for (const item of issue.path)if ("string" != typeof item.key && "number" != typeof item.key) return null;
39437
+ else if (key) key += `.${item.key}`;
39438
+ else key += item.key;
39439
+ return key;
39440
+ }
39441
+ return null;
39442
+ }
39443
+ function dist_nonEmpty(message$1) {
39416
39444
  return {
39417
39445
  kind: "validation",
39418
- type: "min_value",
39419
- reference: minValue,
39446
+ type: "non_empty",
39447
+ reference: dist_nonEmpty,
39420
39448
  async: false,
39421
- expects: `>=${requirement instanceof Date ? requirement.toJSON() : /* @__PURE__ */ _stringify(requirement)}`,
39422
- requirement,
39449
+ expects: "!0",
39423
39450
  message: message$1,
39424
39451
  "~run" (dataset, config$1) {
39425
- if (dataset.typed && !(dataset.value >= this.requirement)) _addIssue(this, "value", dataset, config$1, {
39426
- received: dataset.value instanceof Date ? dataset.value.toJSON() : /* @__PURE__ */ _stringify(dataset.value)
39452
+ if (dataset.typed && 0 === dataset.value.length) _addIssue(this, "length", dataset, config$1, {
39453
+ received: "0"
39427
39454
  });
39428
39455
  return dataset;
39429
39456
  }
@@ -39533,53 +39560,30 @@ var __webpack_exports__ = {};
39533
39560
  }
39534
39561
  };
39535
39562
  }
39536
- function nullable(wrapped, default_) {
39563
+ function custom(check$1, message$1) {
39537
39564
  return {
39538
39565
  kind: "schema",
39539
- type: "nullable",
39540
- reference: nullable,
39541
- expects: `(${wrapped.expects} | null)`,
39542
- async: false,
39543
- wrapped,
39544
- default: default_,
39545
- get "~standard" () {
39546
- return /* @__PURE__ */ _getStandardProps(this);
39547
- },
39548
- "~run" (dataset, config$1) {
39549
- if (null === dataset.value) {
39550
- if (void 0 !== this.default) dataset.value = /* @__PURE__ */ getDefault(this, dataset, config$1);
39551
- if (null === dataset.value) {
39552
- dataset.typed = true;
39553
- return dataset;
39554
- }
39555
- }
39556
- return this.wrapped["~run"](dataset, config$1);
39557
- }
39558
- };
39559
- }
39560
- function dist_number(message$1) {
39561
- return {
39562
- kind: "schema",
39563
- type: "number",
39564
- reference: dist_number,
39565
- expects: "number",
39566
+ type: "custom",
39567
+ reference: custom,
39568
+ expects: "unknown",
39566
39569
  async: false,
39570
+ check: check$1,
39567
39571
  message: message$1,
39568
39572
  get "~standard" () {
39569
39573
  return /* @__PURE__ */ _getStandardProps(this);
39570
39574
  },
39571
39575
  "~run" (dataset, config$1) {
39572
- if ("number" != typeof dataset.value || isNaN(dataset.value)) _addIssue(this, "type", dataset, config$1);
39573
- else dataset.typed = true;
39576
+ if (this.check(dataset.value)) dataset.typed = true;
39577
+ else _addIssue(this, "type", dataset, config$1);
39574
39578
  return dataset;
39575
39579
  }
39576
39580
  };
39577
39581
  }
39578
- function dist_object(entries$1, message$1) {
39582
+ function looseObject(entries$1, message$1) {
39579
39583
  return {
39580
39584
  kind: "schema",
39581
- type: "object",
39582
- reference: dist_object,
39585
+ type: "loose_object",
39586
+ reference: looseObject,
39583
39587
  expects: "Object",
39584
39588
  async: false,
39585
39589
  entries: entries$1,
@@ -39640,17 +39644,20 @@ var __webpack_exports__ = {};
39640
39644
  if (config$1.abortEarly) break;
39641
39645
  }
39642
39646
  }
39647
+ if (!dataset.issues || !config$1.abortEarly) {
39648
+ for(const key in input)if (/* @__PURE__ */ _isValidObjectKey(input, key) && !(key in this.entries)) dataset.value[key] = input[key];
39649
+ }
39643
39650
  } else _addIssue(this, "type", dataset, config$1);
39644
39651
  return dataset;
39645
39652
  }
39646
39653
  };
39647
39654
  }
39648
- function optional(wrapped, default_) {
39655
+ function nullable(wrapped, default_) {
39649
39656
  return {
39650
39657
  kind: "schema",
39651
- type: "optional",
39652
- reference: optional,
39653
- expects: `(${wrapped.expects} | undefined)`,
39658
+ type: "nullable",
39659
+ reference: nullable,
39660
+ expects: `(${wrapped.expects} | null)`,
39654
39661
  async: false,
39655
39662
  wrapped,
39656
39663
  default: default_,
@@ -39658,9 +39665,9 @@ var __webpack_exports__ = {};
39658
39665
  return /* @__PURE__ */ _getStandardProps(this);
39659
39666
  },
39660
39667
  "~run" (dataset, config$1) {
39661
- if (void 0 === dataset.value) {
39668
+ if (null === dataset.value) {
39662
39669
  if (void 0 !== this.default) dataset.value = /* @__PURE__ */ getDefault(this, dataset, config$1);
39663
- if (void 0 === dataset.value) {
39670
+ if (null === dataset.value) {
39664
39671
  dataset.typed = true;
39665
39672
  return dataset;
39666
39673
  }
@@ -39669,151 +39676,81 @@ var __webpack_exports__ = {};
39669
39676
  }
39670
39677
  };
39671
39678
  }
39672
- function record(key, value$1, message$1) {
39679
+ function dist_number(message$1) {
39673
39680
  return {
39674
39681
  kind: "schema",
39675
- type: "record",
39676
- reference: record,
39677
- expects: "Object",
39682
+ type: "number",
39683
+ reference: dist_number,
39684
+ expects: "number",
39678
39685
  async: false,
39679
- key,
39680
- value: value$1,
39681
39686
  message: message$1,
39682
39687
  get "~standard" () {
39683
39688
  return /* @__PURE__ */ _getStandardProps(this);
39684
39689
  },
39685
39690
  "~run" (dataset, config$1) {
39686
- const input = dataset.value;
39687
- if (input && "object" == typeof input) {
39688
- dataset.typed = true;
39689
- dataset.value = {};
39690
- for(const entryKey in input)if (/* @__PURE__ */ _isValidObjectKey(input, entryKey)) {
39691
- const entryValue = input[entryKey];
39692
- const keyDataset = this.key["~run"]({
39693
- value: entryKey
39694
- }, config$1);
39695
- if (keyDataset.issues) {
39696
- const pathItem = {
39697
- type: "object",
39698
- origin: "key",
39699
- input,
39700
- key: entryKey,
39701
- value: entryValue
39702
- };
39703
- for (const issue of keyDataset.issues){
39704
- issue.path = [
39705
- pathItem
39706
- ];
39707
- dataset.issues?.push(issue);
39708
- }
39709
- if (!dataset.issues) dataset.issues = keyDataset.issues;
39710
- if (config$1.abortEarly) {
39711
- dataset.typed = false;
39712
- break;
39713
- }
39714
- }
39715
- const valueDataset = this.value["~run"]({
39716
- value: entryValue
39717
- }, config$1);
39718
- if (valueDataset.issues) {
39719
- const pathItem = {
39720
- type: "object",
39721
- origin: "value",
39722
- input,
39723
- key: entryKey,
39724
- value: entryValue
39725
- };
39726
- for (const issue of valueDataset.issues){
39727
- if (issue.path) issue.path.unshift(pathItem);
39728
- else issue.path = [
39729
- pathItem
39730
- ];
39731
- dataset.issues?.push(issue);
39732
- }
39733
- if (!dataset.issues) dataset.issues = valueDataset.issues;
39734
- if (config$1.abortEarly) {
39735
- dataset.typed = false;
39736
- break;
39737
- }
39738
- }
39739
- if (!keyDataset.typed || !valueDataset.typed) dataset.typed = false;
39740
- if (keyDataset.typed) dataset.value[keyDataset.value] = valueDataset.value;
39741
- }
39742
- } else _addIssue(this, "type", dataset, config$1);
39691
+ if ("number" != typeof dataset.value || isNaN(dataset.value)) _addIssue(this, "type", dataset, config$1);
39692
+ else dataset.typed = true;
39743
39693
  return dataset;
39744
39694
  }
39745
39695
  };
39746
39696
  }
39747
- function dist_string(message$1) {
39697
+ function optional(wrapped, default_) {
39748
39698
  return {
39749
39699
  kind: "schema",
39750
- type: "string",
39751
- reference: dist_string,
39752
- expects: "string",
39700
+ type: "optional",
39701
+ reference: optional,
39702
+ expects: `(${wrapped.expects} | undefined)`,
39703
+ async: false,
39704
+ wrapped,
39705
+ default: default_,
39706
+ get "~standard" () {
39707
+ return /* @__PURE__ */ _getStandardProps(this);
39708
+ },
39709
+ "~run" (dataset, config$1) {
39710
+ if (void 0 === dataset.value) {
39711
+ if (void 0 !== this.default) dataset.value = /* @__PURE__ */ getDefault(this, dataset, config$1);
39712
+ if (void 0 === dataset.value) {
39713
+ dataset.typed = true;
39714
+ return dataset;
39715
+ }
39716
+ }
39717
+ return this.wrapped["~run"](dataset, config$1);
39718
+ }
39719
+ };
39720
+ }
39721
+ function picklist(options, message$1) {
39722
+ return {
39723
+ kind: "schema",
39724
+ type: "picklist",
39725
+ reference: picklist,
39726
+ expects: /* @__PURE__ */ _joinExpects(options.map(_stringify), "|"),
39753
39727
  async: false,
39728
+ options,
39754
39729
  message: message$1,
39755
39730
  get "~standard" () {
39756
39731
  return /* @__PURE__ */ _getStandardProps(this);
39757
39732
  },
39758
39733
  "~run" (dataset, config$1) {
39759
- if ("string" == typeof dataset.value) dataset.typed = true;
39734
+ if (this.options.includes(dataset.value)) dataset.typed = true;
39760
39735
  else _addIssue(this, "type", dataset, config$1);
39761
39736
  return dataset;
39762
39737
  }
39763
39738
  };
39764
39739
  }
39765
- function _subIssues(datasets) {
39766
- let issues;
39767
- if (datasets) for (const dataset of datasets)if (issues) issues.push(...dataset.issues);
39768
- else issues = dataset.issues;
39769
- return issues;
39770
- }
39771
- function union(options, message$1) {
39740
+ function dist_string(message$1) {
39772
39741
  return {
39773
39742
  kind: "schema",
39774
- type: "union",
39775
- reference: union,
39776
- expects: /* @__PURE__ */ _joinExpects(options.map((option)=>option.expects), "|"),
39743
+ type: "string",
39744
+ reference: dist_string,
39745
+ expects: "string",
39777
39746
  async: false,
39778
- options,
39779
39747
  message: message$1,
39780
39748
  get "~standard" () {
39781
39749
  return /* @__PURE__ */ _getStandardProps(this);
39782
39750
  },
39783
39751
  "~run" (dataset, config$1) {
39784
- let validDataset;
39785
- let typedDatasets;
39786
- let untypedDatasets;
39787
- for (const schema of this.options){
39788
- const optionDataset = schema["~run"]({
39789
- value: dataset.value
39790
- }, config$1);
39791
- if (optionDataset.typed) if (optionDataset.issues) if (typedDatasets) typedDatasets.push(optionDataset);
39792
- else typedDatasets = [
39793
- optionDataset
39794
- ];
39795
- else {
39796
- validDataset = optionDataset;
39797
- break;
39798
- }
39799
- else if (untypedDatasets) untypedDatasets.push(optionDataset);
39800
- else untypedDatasets = [
39801
- optionDataset
39802
- ];
39803
- }
39804
- if (validDataset) return validDataset;
39805
- if (typedDatasets) {
39806
- if (1 === typedDatasets.length) return typedDatasets[0];
39807
- _addIssue(this, "type", dataset, config$1, {
39808
- issues: /* @__PURE__ */ _subIssues(typedDatasets)
39809
- });
39810
- dataset.typed = true;
39811
- } else {
39812
- if (untypedDatasets?.length === 1) return untypedDatasets[0];
39813
- _addIssue(this, "type", dataset, config$1, {
39814
- issues: /* @__PURE__ */ _subIssues(untypedDatasets)
39815
- });
39816
- }
39752
+ if ("string" == typeof dataset.value) dataset.typed = true;
39753
+ else _addIssue(this, "type", dataset, config$1);
39817
39754
  return dataset;
39818
39755
  }
39819
39756
  };
@@ -40159,7 +40096,7 @@ var __webpack_exports__ = {};
40159
40096
  if (!preferredEditors.includes(normalized)) throw new Error(`✖ Error: preferredEditor must be one of: ${preferredEditors.join(", ")} (alias: code -> vscode)`);
40160
40097
  return normalized;
40161
40098
  }
40162
- if ("anvilUrl" === key) return value.trim().replace(/\/+$/, "");
40099
+ if ("anvilUrl" === key) return config_normalizeAnvilUrl(value);
40163
40100
  return coerceConfigValue(key, value);
40164
40101
  }
40165
40102
  function config_getPreferredEditorCommand(preferredEditorValue) {
@@ -43299,91 +43236,753 @@ var __webpack_exports__ = {};
43299
43236
  return filesToRemove;
43300
43237
  }
43301
43238
  var external_crypto_ = __webpack_require__("crypto");
43302
- const FormTemplateSchema = dist_object({
43303
- is_package: optional(dist_boolean()),
43304
- container: optional(dist_object({
43305
- type: dist_string(),
43306
- properties: optional(any())
43307
- })),
43308
- components: optional(dist_array(any())),
43309
- layout: optional(dist_object({
43310
- type: dist_string(),
43311
- properties: optional(any())
43312
- })),
43313
- components_by_slot: optional(record(dist_string(), dist_array(any()))),
43314
- custom_component: optional(dist_boolean()),
43315
- custom_component_container: optional(dist_boolean()),
43316
- properties: optional(dist_array(any())),
43317
- events: optional(dist_array(any())),
43318
- toolbox_item: optional(any()),
43319
- layout_metadata: optional(any()),
43320
- slots: optional(any()),
43321
- item_type: optional(dist_object({
43322
- table_id: dist_number()
43323
- }))
43324
- });
43239
+ const BUILTIN_COMPONENT_TYPES = new Set([
43240
+ "Label",
43241
+ "RichText",
43242
+ "Link",
43243
+ "Button",
43244
+ "TextBox",
43245
+ "TextArea",
43246
+ "CheckBox",
43247
+ "RadioButton",
43248
+ "DropDown",
43249
+ "DatePicker",
43250
+ "Timer",
43251
+ "Canvas",
43252
+ "Image",
43253
+ "YouTubeVideo",
43254
+ "GoogleMap",
43255
+ "Plot",
43256
+ "FileLoader",
43257
+ "Spacer",
43258
+ "GridPanel",
43259
+ "LinearPanel",
43260
+ "XYPanel",
43261
+ "ColumnPanel",
43262
+ "HtmlPanel",
43263
+ "RepeatingPanel",
43264
+ "DataGrid",
43265
+ "DataRowPanel",
43266
+ "CustomComponent",
43267
+ "LayoutSlot",
43268
+ "FlowPanel",
43269
+ "HtmlTemplate"
43270
+ ]);
43271
+ const KNOWN_RUNTIME_SERVICE_SOURCES = new Set([
43272
+ "/runtime/services/tables.yml",
43273
+ "/runtime/services/google.yml",
43274
+ "/runtime/services/uplink.yml",
43275
+ "/runtime/services/stripe.yml",
43276
+ "/runtime/services/segment.yml",
43277
+ "/runtime/services/facebook.yml",
43278
+ "/runtime/services/anvil/users.yml",
43279
+ "/runtime/services/anvil/secrets.yml",
43280
+ "/runtime/services/anvil/saml.yml",
43281
+ "/runtime/services/anvil/microsoft.yml",
43282
+ "/runtime/services/anvil/email.yml",
43283
+ "/runtime/services/anvil/files.yml"
43284
+ ]);
43285
+ const IDENTIFIER_RE = /^[A-Za-z_][A-Za-z0-9_]*$/;
43286
+ const DEP_ID_RE = /^dep_[A-Za-z0-9]+$/;
43287
+ const DB_ACCESS_LEVELS = new Set([
43288
+ "none",
43289
+ "search",
43290
+ "full"
43291
+ ]);
43292
+ const DB_BASIC_COLUMN_TYPES = new Set([
43293
+ "string",
43294
+ "number",
43295
+ "bool",
43296
+ "date",
43297
+ "datetime",
43298
+ "media",
43299
+ "simpleObject"
43300
+ ]);
43301
+ const DB_LINK_COLUMN_TYPES = new Set([
43302
+ "link_single",
43303
+ "link_multiple"
43304
+ ]);
43305
+ const DB_TABLE_INDEX_TYPES = new Set([
43306
+ "b_tree",
43307
+ "trigram",
43308
+ "full_text"
43309
+ ]);
43310
+ const SCHEDULE_EVERY_VALUES = new Set([
43311
+ "minute",
43312
+ "hour",
43313
+ "day",
43314
+ "week",
43315
+ "month"
43316
+ ]);
43317
+ const CLIENT_VERSIONS = new Set([
43318
+ "2",
43319
+ "3"
43320
+ ]);
43321
+ const PYTHON_KEYWORDS = new Set([
43322
+ "False",
43323
+ "None",
43324
+ "True",
43325
+ "and",
43326
+ "as",
43327
+ "assert",
43328
+ "async",
43329
+ "await",
43330
+ "break",
43331
+ "class",
43332
+ "continue",
43333
+ "def",
43334
+ "del",
43335
+ "elif",
43336
+ "else",
43337
+ "except",
43338
+ "finally",
43339
+ "for",
43340
+ "from",
43341
+ "global",
43342
+ "if",
43343
+ "import",
43344
+ "in",
43345
+ "is",
43346
+ "lambda",
43347
+ "nonlocal",
43348
+ "not",
43349
+ "or",
43350
+ "pass",
43351
+ "raise",
43352
+ "return",
43353
+ "try",
43354
+ "while",
43355
+ "with",
43356
+ "yield",
43357
+ "match",
43358
+ "case"
43359
+ ]);
43360
+ const PROPERTY_TYPES = new Set([
43361
+ "string",
43362
+ "number",
43363
+ "color",
43364
+ "boolean",
43365
+ "text[]",
43366
+ "enum",
43367
+ "icon",
43368
+ "form",
43369
+ "object",
43370
+ "uri",
43371
+ "margin",
43372
+ "padding",
43373
+ "spacing"
43374
+ ]);
43375
+ function isValidFormReference(typeName) {
43376
+ if (!typeName.startsWith("form:")) return false;
43377
+ const rest = typeName.slice(5);
43378
+ if (0 === rest.length) return false;
43379
+ let classPath = rest;
43380
+ if (rest.startsWith("dep_")) {
43381
+ const splitIndex = rest.indexOf(":");
43382
+ if (splitIndex <= 0) return false;
43383
+ const depId = rest.slice(0, splitIndex);
43384
+ if (!DEP_ID_RE.test(depId)) return false;
43385
+ classPath = rest.slice(splitIndex + 1);
43386
+ }
43387
+ if (0 === classPath.length) return false;
43388
+ return classPath.split(".").every((part)=>IDENTIFIER_RE.test(part));
43389
+ }
43390
+ function isBuiltinComponentType(typeName) {
43391
+ return BUILTIN_COMPONENT_TYPES.has(typeName);
43392
+ }
43393
+ function isPlainObject(value) {
43394
+ return "object" == typeof value && null !== value && !Array.isArray(value);
43395
+ }
43396
+ function pushIssue(issues, path, message) {
43397
+ issues.push({
43398
+ path,
43399
+ message
43400
+ });
43401
+ }
43402
+ function formatValidationPath(path) {
43403
+ return path || "root";
43404
+ }
43405
+ function validateIdentifier(value, path, issues) {
43406
+ if ("string" != typeof value || 0 === value.length) return void pushIssue(issues, path, "must be a non-empty string");
43407
+ if (!IDENTIFIER_RE.test(value)) return void pushIssue(issues, path, "must be a valid identifier");
43408
+ if (PYTHON_KEYWORDS.has(value)) pushIssue(issues, path, "must be a valid Python identifier (not a keyword)");
43409
+ }
43410
+ function validateComponentType(value, path, issues) {
43411
+ if ("string" != typeof value || 0 === value.length) return void pushIssue(issues, path, "must be a non-empty string");
43412
+ const typeName = value;
43413
+ if (typeName.startsWith("form:")) {
43414
+ if (!isValidFormReference(typeName)) pushIssue(issues, path, "must be a valid form: reference (form:Module.Form, form:dep_xxx:Package.Form)");
43415
+ return;
43416
+ }
43417
+ if (!IDENTIFIER_RE.test(typeName)) return void pushIssue(issues, path, "must be a valid identifier");
43418
+ if (PYTHON_KEYWORDS.has(typeName)) return void pushIssue(issues, path, "must be a valid Python identifier (not a keyword)");
43419
+ if (!isBuiltinComponentType(typeName)) pushIssue(issues, path, "must be a known Anvil component type (see componentIcons.ts) or a form: reference");
43420
+ }
43421
+ function validatePropertiesObject(value, path, issues) {
43422
+ if (void 0 !== value && !isPlainObject(value)) pushIssue(issues, path, "must be an object");
43423
+ }
43424
+ function validateEventBindingsObject(value, path, issues) {
43425
+ if (void 0 === value) return;
43426
+ if (!isPlainObject(value)) return void pushIssue(issues, path, "must be an object");
43427
+ for (const [eventName, handlerName] of Object.entries(value)){
43428
+ validateIdentifier(eventName, `${path}.${eventName}.name`, issues);
43429
+ validateIdentifier(handlerName, `${path}.${eventName}`, issues);
43430
+ }
43431
+ }
43432
+ function validateDataBindings(value, path, issues) {
43433
+ if (void 0 === value) return;
43434
+ if (!Array.isArray(value)) return void pushIssue(issues, path, "must be an array");
43435
+ value.forEach((binding, index)=>{
43436
+ const bindingPath = `${path}[${index}]`;
43437
+ if (!isPlainObject(binding)) return void pushIssue(issues, bindingPath, "must be an object");
43438
+ if ("string" != typeof binding.property || 0 === binding.property.length) pushIssue(issues, `${bindingPath}.property`, "must be a non-empty string");
43439
+ if ("string" != typeof binding.code || 0 === binding.code.length) pushIssue(issues, `${bindingPath}.code`, "must be a non-empty string");
43440
+ if (void 0 !== binding.writeback && "boolean" != typeof binding.writeback) pushIssue(issues, `${bindingPath}.writeback`, "must be a boolean");
43441
+ });
43442
+ }
43443
+ function validateComponentArray(components, pathPrefix, issues, seenNames) {
43444
+ components.forEach((component, index)=>{
43445
+ const childPath = `${pathPrefix}[${index}]`;
43446
+ validateComponentNode(component, childPath, issues, seenNames);
43447
+ if (isPlainObject(component) && "string" == typeof component.name && component.name.length > 0) {
43448
+ if (seenNames.has(component.name)) pushIssue(issues, `${childPath}.name`, "must be unique across form components");
43449
+ seenNames.add(component.name);
43450
+ }
43451
+ });
43452
+ }
43453
+ function validateComponentNode(value, path, issues, seenNames) {
43454
+ if (!isPlainObject(value)) return void pushIssue(issues, path, "must be an object");
43455
+ validateComponentType(value.type, `${path}.type`, issues);
43456
+ if (void 0 === value.name || "string" != typeof value.name || 0 === value.name.length) pushIssue(issues, `${path}.name`, "must be a non-empty string");
43457
+ else validateIdentifier(value.name, `${path}.name`, issues);
43458
+ validatePropertiesObject(value.properties, `${path}.properties`, issues);
43459
+ validatePropertiesObject(value.layout_properties, `${path}.layout_properties`, issues);
43460
+ validateEventBindingsObject(value.event_bindings, `${path}.event_bindings`, issues);
43461
+ validateDataBindings(value.data_bindings, `${path}.data_bindings`, issues);
43462
+ if (void 0 !== value.components) if (Array.isArray(value.components)) validateComponentArray(value.components, `${path}.components`, issues, seenNames);
43463
+ else pushIssue(issues, `${path}.components`, "must be an array");
43464
+ }
43465
+ function validatePropertyDefinition(value, path, issues) {
43466
+ if (!isPlainObject(value)) return void pushIssue(issues, path, "must be an object");
43467
+ validateIdentifier(value.name, `${path}.name`, issues);
43468
+ if ("string" != typeof value.type || !PROPERTY_TYPES.has(value.type)) pushIssue(issues, `${path}.type`, "must be a supported property type");
43469
+ if (void 0 !== value.description && "string" != typeof value.description) pushIssue(issues, `${path}.description`, "must be a string");
43470
+ if (void 0 !== value.default_binding_prop && "boolean" != typeof value.default_binding_prop) pushIssue(issues, `${path}.default_binding_prop`, "must be a boolean");
43471
+ if (void 0 !== value.allow_binding_writeback && "boolean" != typeof value.allow_binding_writeback) pushIssue(issues, `${path}.allow_binding_writeback`, "must be a boolean");
43472
+ if (void 0 !== value.binding_writeback_events) if (Array.isArray(value.binding_writeback_events)) value.binding_writeback_events.forEach((eventName, index)=>{
43473
+ if ("string" != typeof eventName || 0 === eventName.length) pushIssue(issues, `${path}.binding_writeback_events[${index}]`, "must be a non-empty string");
43474
+ });
43475
+ else pushIssue(issues, `${path}.binding_writeback_events`, "must be an array");
43476
+ if ("enum" === value.type) {
43477
+ if (!Array.isArray(value.options) || value.options.some((option)=>"string" != typeof option)) pushIssue(issues, `${path}.options`, "must be an array of strings for enum properties");
43478
+ }
43479
+ }
43480
+ function validateEventDefinition(value, path, issues) {
43481
+ if (!isPlainObject(value)) return void pushIssue(issues, path, "must be an object");
43482
+ validateIdentifier(value.name, `${path}.name`, issues);
43483
+ if (void 0 !== value.description && "string" != typeof value.description) pushIssue(issues, `${path}.description`, "must be a string");
43484
+ if (void 0 !== value.default_event && "boolean" != typeof value.default_event) pushIssue(issues, `${path}.default_event`, "must be a boolean");
43485
+ if (void 0 !== value.parameters) if (Array.isArray(value.parameters)) value.parameters.forEach((parameter, index)=>{
43486
+ if (!isPlainObject(parameter)) return void pushIssue(issues, `${path}.parameters[${index}]`, "must be an object");
43487
+ validateIdentifier(parameter.name, `${path}.parameters[${index}].name`, issues);
43488
+ if (void 0 !== parameter.description && "string" != typeof parameter.description) pushIssue(issues, `${path}.parameters[${index}].description`, "must be a string");
43489
+ });
43490
+ else pushIssue(issues, `${path}.parameters`, "must be an array");
43491
+ }
43492
+ function validateSlotDefinition(value, path, issues, seenNames) {
43493
+ if (!isPlainObject(value)) return void pushIssue(issues, path, "must be an object");
43494
+ if ("number" != typeof value.index || !Number.isInteger(value.index) || value.index < 0) pushIssue(issues, `${path}.index`, "must be a non-negative integer");
43495
+ validatePropertiesObject(value.set_layout_properties, `${path}.set_layout_properties`, issues);
43496
+ if (isPlainObject(value.target)) {
43497
+ if ("container" !== value.target.type && "slot" !== value.target.type) pushIssue(issues, `${path}.target.type`, "must be 'container' or 'slot'");
43498
+ validateIdentifier(value.target.name, `${path}.target.name`, issues);
43499
+ } else pushIssue(issues, `${path}.target`, "must be an object");
43500
+ if (void 0 !== value.template) validateComponentNode(value.template, `${path}.template`, issues, seenNames);
43501
+ }
43502
+ function validateFormTemplateData(value) {
43503
+ const issues = [];
43504
+ const componentNames = new Set();
43505
+ if (!isPlainObject(value)) {
43506
+ pushIssue(issues, "", "must be a YAML object");
43507
+ return issues;
43508
+ }
43509
+ const hasContainer = void 0 !== value.container;
43510
+ const hasLayout = void 0 !== value.layout;
43511
+ const hasComponents = void 0 !== value.components;
43512
+ const hasComponentsBySlot = void 0 !== value.components_by_slot;
43513
+ if (hasContainer && hasLayout) pushIssue(issues, "", "cannot define both container and layout");
43514
+ if (!hasContainer && !hasLayout) pushIssue(issues, "", "must define either container or layout");
43515
+ if (void 0 !== value.is_package && "boolean" != typeof value.is_package) pushIssue(issues, "is_package", "must be a boolean");
43516
+ if (hasContainer) if (isPlainObject(value.container)) {
43517
+ validateComponentType(value.container.type, "container.type", issues);
43518
+ validatePropertiesObject(value.container.properties, "container.properties", issues);
43519
+ validatePropertiesObject(value.container.layout_properties, "container.layout_properties", issues);
43520
+ validateEventBindingsObject(value.container.event_bindings, "container.event_bindings", issues);
43521
+ validateDataBindings(value.container.data_bindings, "container.data_bindings", issues);
43522
+ } else pushIssue(issues, "container", "must be an object");
43523
+ if (hasLayout) if (isPlainObject(value.layout)) {
43524
+ validateComponentType(value.layout.type, "layout.type", issues);
43525
+ validatePropertiesObject(value.layout.properties, "layout.properties", issues);
43526
+ validateEventBindingsObject(value.layout.event_bindings, "layout.event_bindings", issues);
43527
+ validateEventBindingsObject(value.layout.form_event_bindings, "layout.form_event_bindings", issues);
43528
+ validateDataBindings(value.layout.data_bindings, "layout.data_bindings", issues);
43529
+ } else pushIssue(issues, "layout", "must be an object");
43530
+ if (hasComponents && hasLayout) pushIssue(issues, "components", "can only be used with container-based forms");
43531
+ else if (hasComponents && !hasContainer) pushIssue(issues, "components", "can only be used with container-based forms");
43532
+ else if (hasComponents) if (Array.isArray(value.components)) validateComponentArray(value.components, "components", issues, componentNames);
43533
+ else pushIssue(issues, "components", "must be an array");
43534
+ if (hasComponentsBySlot && hasContainer) pushIssue(issues, "components_by_slot", "can only be used with layout-based forms");
43535
+ else if (hasComponentsBySlot && !hasLayout) pushIssue(issues, "components_by_slot", "can only be used with layout-based forms");
43536
+ else if (hasComponentsBySlot) if (isPlainObject(value.components_by_slot)) for (const [slotName, slotComponents] of Object.entries(value.components_by_slot)){
43537
+ if (!Array.isArray(slotComponents)) {
43538
+ pushIssue(issues, `components_by_slot.${slotName}`, "must be an array");
43539
+ continue;
43540
+ }
43541
+ validateComponentArray(slotComponents, `components_by_slot.${slotName}`, issues, componentNames);
43542
+ }
43543
+ else pushIssue(issues, "components_by_slot", "must be an object");
43544
+ if (void 0 !== value.custom_component && "boolean" != typeof value.custom_component) pushIssue(issues, "custom_component", "must be a boolean");
43545
+ if (void 0 !== value.custom_component_container && "boolean" != typeof value.custom_component_container) pushIssue(issues, "custom_component_container", "must be a boolean");
43546
+ if (true === value.custom_component_container && true !== value.custom_component) pushIssue(issues, "custom_component_container", "requires custom_component: true");
43547
+ const properties = value.properties;
43548
+ if (void 0 !== properties) if (Array.isArray(properties)) {
43549
+ const seenNames = new Set();
43550
+ let defaultBindingPropCount = 0;
43551
+ properties.forEach((property, index)=>{
43552
+ validatePropertyDefinition(property, `properties[${index}]`, issues);
43553
+ if (!isPlainObject(property) || "string" != typeof property.name) return;
43554
+ if (seenNames.has(property.name)) pushIssue(issues, `properties[${index}].name`, "must be unique");
43555
+ seenNames.add(property.name);
43556
+ if (property.default_binding_prop) defaultBindingPropCount++;
43557
+ });
43558
+ if (defaultBindingPropCount > 1) pushIssue(issues, "properties", "can only define one default_binding_prop");
43559
+ } else pushIssue(issues, "properties", "must be an array");
43560
+ const events = value.events;
43561
+ const eventNames = new Set();
43562
+ if (void 0 !== events) if (Array.isArray(events)) {
43563
+ let defaultEventCount = 0;
43564
+ events.forEach((event, index)=>{
43565
+ validateEventDefinition(event, `events[${index}]`, issues);
43566
+ if (!isPlainObject(event) || "string" != typeof event.name) return;
43567
+ if (eventNames.has(event.name)) pushIssue(issues, `events[${index}].name`, "must be unique");
43568
+ eventNames.add(event.name);
43569
+ if (event.default_event) defaultEventCount++;
43570
+ });
43571
+ if (defaultEventCount > 1) pushIssue(issues, "events", "can only define one default_event");
43572
+ } else pushIssue(issues, "events", "must be an array");
43573
+ if (Array.isArray(properties)) properties.forEach((property, index)=>{
43574
+ if (!isPlainObject(property) || !Array.isArray(property.binding_writeback_events)) return;
43575
+ property.binding_writeback_events.forEach((eventName, eventIndex)=>{
43576
+ if ("string" == typeof eventName && !eventNames.has(eventName)) pushIssue(issues, `properties[${index}].binding_writeback_events[${eventIndex}]`, "must reference a defined event");
43577
+ });
43578
+ });
43579
+ if (void 0 !== value.slots) if (isPlainObject(value.slots)) for (const [slotName, slotDef] of Object.entries(value.slots)){
43580
+ validateIdentifier(slotName, `slots.${slotName}.name`, issues);
43581
+ validateSlotDefinition(slotDef, `slots.${slotName}`, issues, componentNames);
43582
+ }
43583
+ else pushIssue(issues, "slots", "must be an object");
43584
+ if (void 0 !== value.item_type) if (isPlainObject(value.item_type)) {
43585
+ if ("number" != typeof value.item_type.table_id) pushIssue(issues, "item_type.table_id", "must be a number");
43586
+ } else pushIssue(issues, "item_type", "must be an object");
43587
+ return issues;
43588
+ }
43325
43589
  function validateFormTemplate(yamlContent) {
43326
43590
  try {
43327
43591
  const data = load(yamlContent);
43328
- const result = safeParse(FormTemplateSchema, data);
43329
- if (!result.success) {
43330
- logger_logger.error("form_template.yaml: Validation failed");
43331
- for (const issue of result.issues)logger_logger.error(` - ${issue.path?.map((p)=>p.key).join(".") || "root"}: ${issue.message}`);
43332
- return false;
43333
- }
43334
- return true;
43592
+ const issues = validateFormTemplateData(data);
43593
+ if (issues.length > 0) return {
43594
+ ok: false,
43595
+ message: "form_template.yaml is invalid for Anvil",
43596
+ issues
43597
+ };
43598
+ return {
43599
+ ok: true
43600
+ };
43335
43601
  } catch (error) {
43336
- logger_logger.error(`form_template.yaml: YAML parse error: ${error}`);
43337
- return false;
43602
+ return {
43603
+ ok: false,
43604
+ message: "form_template.yaml is not valid YAML",
43605
+ issues: [
43606
+ {
43607
+ path: "",
43608
+ message: error instanceof Error ? error.message : String(error)
43609
+ }
43610
+ ]
43611
+ };
43612
+ }
43613
+ }
43614
+ const serviceConfigObject = custom((input)=>isPlainObject(input), "must be an object");
43615
+ const AnvilServiceEntrySchema = looseObject({
43616
+ source: pipe(dist_string(), dist_nonEmpty()),
43617
+ client_config: optional(serviceConfigObject),
43618
+ server_config: optional(serviceConfigObject)
43619
+ });
43620
+ const RuntimeOptionsSchema = looseObject({
43621
+ version: dist_number(),
43622
+ client_version: optional(picklist([
43623
+ "2",
43624
+ "3"
43625
+ ])),
43626
+ preview_v3: optional(dist_boolean()),
43627
+ server_version: optional(dist_string()),
43628
+ server_persist: optional(dist_boolean()),
43629
+ legacy_features: optional(looseObject({
43630
+ class_names: optional(dist_boolean()),
43631
+ bootstrap3: optional(dist_boolean()),
43632
+ __dict__: optional(dist_boolean()),
43633
+ root_container: optional(dist_boolean())
43634
+ })),
43635
+ server_spec: optional(nullable(looseObject({
43636
+ base: optional(dist_string())
43637
+ })))
43638
+ });
43639
+ function validateRuntimeOptions(value, path) {
43640
+ const issues = [];
43641
+ if (void 0 === value) return issues;
43642
+ if (!isPlainObject(value)) return issues;
43643
+ if (void 0 !== value.client_version) {
43644
+ if ("string" != typeof value.client_version || !CLIENT_VERSIONS.has(value.client_version)) pushIssue(issues, `${path}.client_version`, 'must be "2" or "3"');
43645
+ }
43646
+ if (void 0 !== value.server_spec && null !== value.server_spec) {
43647
+ if (!isPlainObject(value.server_spec)) return issues;
43648
+ if ("requirements" in value.server_spec) pushIssue(issues, `${path}.server_spec.requirements`, "is not a valid anvil.yaml field; requirements come from server_code/requirements.txt");
43649
+ if (void 0 !== value.server_spec.base && "string" != typeof value.server_spec.base) pushIssue(issues, `${path}.server_spec.base`, "must be a string");
43338
43650
  }
43651
+ return issues;
43652
+ }
43653
+ function validateDbSchema(value, path) {
43654
+ const issues = [];
43655
+ if (void 0 === value) return issues;
43656
+ if (null === value) {
43657
+ pushIssue(issues, path, "must be an object, an empty array, or omitted");
43658
+ return issues;
43659
+ }
43660
+ if (Array.isArray(value)) {
43661
+ if (0 === value.length) return issues;
43662
+ pushIssue(issues, path, "must be an object mapping table names to schemas, or an empty array");
43663
+ return issues;
43664
+ }
43665
+ if (!isPlainObject(value)) {
43666
+ pushIssue(issues, path, "must be an object mapping table names to schemas");
43667
+ return issues;
43668
+ }
43669
+ for (const tableName of Object.keys(value)){
43670
+ const tablePath = `${path}.${tableName}`;
43671
+ if (!IDENTIFIER_RE.test(tableName)) {
43672
+ pushIssue(issues, tablePath, "must be a valid Python identifier");
43673
+ continue;
43674
+ }
43675
+ const table = value[tableName];
43676
+ if (!isPlainObject(table)) {
43677
+ pushIssue(issues, tablePath, "must be an object");
43678
+ continue;
43679
+ }
43680
+ for (const req of [
43681
+ "client",
43682
+ "server",
43683
+ "title",
43684
+ "columns"
43685
+ ])if (void 0 === table[req]) pushIssue(issues, `${tablePath}.${req}`, "is required");
43686
+ if (void 0 !== table.client) {
43687
+ if ("string" != typeof table.client || !DB_ACCESS_LEVELS.has(table.client)) pushIssue(issues, `${tablePath}.client`, 'must be "none", "search", or "full"');
43688
+ }
43689
+ if (void 0 !== table.server) {
43690
+ if ("string" != typeof table.server || !DB_ACCESS_LEVELS.has(table.server)) pushIssue(issues, `${tablePath}.server`, 'must be "none", "search", or "full"');
43691
+ }
43692
+ if (void 0 !== table.title) {
43693
+ if ("string" != typeof table.title || 0 === table.title.length) pushIssue(issues, `${tablePath}.title`, "must be a non-empty string");
43694
+ }
43695
+ if (void 0 !== table.columns) if (Array.isArray(table.columns)) table.columns.forEach((column, index)=>{
43696
+ validateDbSchemaColumn(column, `${tablePath}.columns[${index}]`, issues);
43697
+ });
43698
+ else pushIssue(issues, `${tablePath}.columns`, "must be an array");
43699
+ if (void 0 !== table.indexes) if (Array.isArray(table.indexes)) table.indexes.forEach((indexEntry, index)=>{
43700
+ validateDbTableIndex(indexEntry, `${tablePath}.indexes[${index}]`, issues);
43701
+ });
43702
+ else pushIssue(issues, `${tablePath}.indexes`, "must be an array");
43703
+ }
43704
+ return issues;
43705
+ }
43706
+ function validateDbTableIndex(value, path, issues) {
43707
+ if (!isPlainObject(value)) return void pushIssue(issues, path, "must be an object");
43708
+ if (!Array.isArray(value.columns) || value.columns.some((c)=>"string" != typeof c)) pushIssue(issues, `${path}.columns`, "must be an array of strings");
43709
+ if (void 0 === value.type) pushIssue(issues, `${path}.type`, "is required");
43710
+ else if ("string" != typeof value.type || !DB_TABLE_INDEX_TYPES.has(value.type)) pushIssue(issues, `${path}.type`, 'must be "b_tree", "trigram", or "full_text"');
43711
+ }
43712
+ function validateDbSchemaColumn(value, path, issues) {
43713
+ if (!isPlainObject(value)) return void pushIssue(issues, path, "must be an object");
43714
+ if (void 0 === value.name || "string" != typeof value.name || 0 === value.name.length) pushIssue(issues, `${path}.name`, "must be a non-empty string");
43715
+ else if (!IDENTIFIER_RE.test(value.name)) pushIssue(issues, `${path}.name`, "must be a valid Python identifier");
43716
+ if (void 0 === value.type) return void pushIssue(issues, `${path}.type`, "is required");
43717
+ if ("string" != typeof value.type) return void pushIssue(issues, `${path}.type`, "must be a string");
43718
+ const colType = value.type;
43719
+ if (DB_LINK_COLUMN_TYPES.has(colType)) {
43720
+ if (void 0 === value.target || "string" != typeof value.target || 0 === value.target.length) pushIssue(issues, `${path}.target`, "must be a non-empty string (target table python name)");
43721
+ else if (!IDENTIFIER_RE.test(value.target)) pushIssue(issues, `${path}.target`, "must be a valid Python identifier");
43722
+ } else if (!DB_BASIC_COLUMN_TYPES.has(colType)) pushIssue(issues, `${path}.type`, `must be a basic column type (${[
43723
+ ...DB_BASIC_COLUMN_TYPES
43724
+ ].join(", ")}) or ${[
43725
+ ...DB_LINK_COLUMN_TYPES
43726
+ ].join(", ")}`);
43727
+ if (void 0 !== value.client_hidden && "boolean" != typeof value.client_hidden) pushIssue(issues, `${path}.client_hidden`, "must be a boolean");
43728
+ if (void 0 !== value.admin_ui && null !== value.admin_ui) if (isPlainObject(value.admin_ui)) {
43729
+ const ui = value.admin_ui;
43730
+ if (void 0 !== ui.width && "number" != typeof ui.width) pushIssue(issues, `${path}.admin_ui.width`, "must be a number");
43731
+ if (void 0 !== ui.order && "number" != typeof ui.order) pushIssue(issues, `${path}.admin_ui.order`, "must be a number");
43732
+ } else pushIssue(issues, `${path}.admin_ui`, "must be an object or null");
43733
+ if (void 0 !== value.indexes) {
43734
+ if (!Array.isArray(value.indexes)) return void pushIssue(issues, `${path}.indexes`, "must be an array");
43735
+ value.indexes.forEach((entry, i)=>{
43736
+ const idxPath = `${path}.indexes[${i}]`;
43737
+ if (!isPlainObject(entry)) return void pushIssue(issues, idxPath, "must be an object");
43738
+ if (void 0 === entry.type) pushIssue(issues, `${idxPath}.type`, "is required");
43739
+ else if ("string" != typeof entry.type || !DB_TABLE_INDEX_TYPES.has(entry.type)) pushIssue(issues, `${idxPath}.type`, 'must be "b_tree", "trigram", or "full_text"');
43740
+ });
43741
+ }
43742
+ }
43743
+ function validateKnownServiceSources(services, path) {
43744
+ const issues = [];
43745
+ if (void 0 === services) return issues;
43746
+ if (!Array.isArray(services)) return issues;
43747
+ services.forEach((service, index)=>{
43748
+ if (!isPlainObject(service) || "string" != typeof service.source) return;
43749
+ if (!KNOWN_RUNTIME_SERVICE_SOURCES.has(service.source)) pushIssue(issues, `${path}[${index}].source`, "must be a known runtime service source path");
43750
+ });
43751
+ return issues;
43339
43752
  }
43340
- const AnvilYamlSchema = dist_object({
43753
+ function validateServiceConfigs(services, path) {
43754
+ const issues = [];
43755
+ if (void 0 === services || !Array.isArray(services)) return issues;
43756
+ services.forEach((service, index)=>{
43757
+ if (!isPlainObject(service) || "/runtime/services/anvil/users.yml" !== service.source) return;
43758
+ if (!isPlainObject(service.client_config)) return;
43759
+ if (true === service.client_config.allow_remember_me && void 0 === service.client_config.remember_me_days) pushIssue(issues, `${path}[${index}].client_config.remember_me_days`, "must be set if allow_remember_me is true");
43760
+ });
43761
+ return issues;
43762
+ }
43763
+ function validateScheduledTasks(value, path) {
43764
+ const issues = [];
43765
+ if (void 0 === value) return issues;
43766
+ if (!Array.isArray(value)) {
43767
+ pushIssue(issues, path, "must be an array");
43768
+ return issues;
43769
+ }
43770
+ value.forEach((task, index)=>{
43771
+ const taskPath = `${path}[${index}]`;
43772
+ if (!isPlainObject(task)) return void pushIssue(issues, taskPath, "must be an object");
43773
+ if ("string" != typeof task.job_id || 0 === task.job_id.length) pushIssue(issues, `${taskPath}.job_id`, "must be a non-empty string");
43774
+ validateIdentifier(task.task_name, `${taskPath}.task_name`, issues);
43775
+ if (!isPlainObject(task.time_spec)) return void pushIssue(issues, `${taskPath}.time_spec`, "must be an object");
43776
+ const timeSpec = task.time_spec;
43777
+ if ("string" != typeof timeSpec.every || !SCHEDULE_EVERY_VALUES.has(timeSpec.every)) pushIssue(issues, `${taskPath}.time_spec.every`, 'must be one of "minute", "hour", "day", "week", or "month"');
43778
+ const interval = timeSpec.n;
43779
+ if (void 0 !== interval && ("number" != typeof interval || !Number.isInteger(interval) || interval <= 0)) pushIssue(issues, `${taskPath}.time_spec.n`, "must be a positive integer");
43780
+ if (void 0 !== timeSpec.at) if (isPlainObject(timeSpec.at)) {
43781
+ const at = timeSpec.at;
43782
+ if (void 0 !== at.minute && !Number.isInteger(at.minute)) pushIssue(issues, `${taskPath}.time_spec.at.minute`, "must be an integer");
43783
+ if (void 0 !== at.hour && !Number.isInteger(at.hour)) pushIssue(issues, `${taskPath}.time_spec.at.hour`, "must be an integer");
43784
+ if (void 0 !== at.day && !Number.isInteger(at.day)) pushIssue(issues, `${taskPath}.time_spec.at.day`, "must be an integer");
43785
+ } else pushIssue(issues, `${taskPath}.time_spec.at`, "must be an object");
43786
+ });
43787
+ return issues;
43788
+ }
43789
+ const AnvilYamlSchema = looseObject({
43341
43790
  name: dist_string(),
43342
- package_name: dist_string(),
43791
+ package_name: optional(dist_string()),
43343
43792
  allow_embedding: optional(dist_boolean()),
43344
43793
  renamed: optional(dist_boolean()),
43345
43794
  dependencies: optional(dist_array(any())),
43346
- runtime_options: dist_object({
43347
- version: pipe(dist_number(), minValue(2)),
43348
- client_version: optional(dist_string()),
43349
- server_version: optional(dist_string()),
43350
- server_spec: optional(any())
43351
- }),
43352
- services: optional(dist_array(dist_object({
43353
- source: dist_string(),
43354
- client_config: optional(any()),
43355
- server_config: optional(any())
43356
- }))),
43357
- startup: optional(union([
43358
- dist_object({
43359
- module: dist_string(),
43360
- type: dist_string()
43361
- }),
43362
- any()
43363
- ])),
43795
+ runtime_options: RuntimeOptionsSchema,
43796
+ services: optional(dist_array(AnvilServiceEntrySchema)),
43797
+ startup: optional(looseObject({
43798
+ type: picklist([
43799
+ "module",
43800
+ "form"
43801
+ ]),
43802
+ module: optional(dist_string())
43803
+ })),
43364
43804
  startup_form: optional(nullable(dist_string())),
43365
43805
  db_schema: optional(any()),
43806
+ scheduled_tasks: optional(any()),
43366
43807
  secrets: optional(any()),
43367
- metadata: optional(any())
43808
+ metadata: optional(looseObject({
43809
+ title: optional(dist_string()),
43810
+ description: optional(dist_string()),
43811
+ logo_img: optional(dist_string())
43812
+ })),
43813
+ client_init_module: optional(dist_string())
43368
43814
  });
43815
+ function formatValibotIssuePath(issue) {
43816
+ return getDotPath(issue) ?? "";
43817
+ }
43369
43818
  function validateAnvilYaml(yamlContent) {
43370
- if (yamlContent.includes("<<<<<<<") || yamlContent.includes(">>>>>>>")) {
43371
- logger_logger.error("anvil.yaml contains git merge conflict markers. Please resolve conflicts manually.");
43372
- return false;
43373
- }
43819
+ if (yamlContent.includes("<<<<<<<") || yamlContent.includes(">>>>>>>")) return {
43820
+ ok: false,
43821
+ message: "anvil.yaml contains merge conflict markers",
43822
+ issues: [
43823
+ {
43824
+ path: "",
43825
+ message: "contains git merge conflict markers"
43826
+ }
43827
+ ]
43828
+ };
43374
43829
  try {
43375
43830
  const data = load(yamlContent);
43376
43831
  const result = safeParse(AnvilYamlSchema, data);
43377
- if (!result.success) {
43378
- logger_logger.error("anvil.yaml: Validation failed");
43379
- for (const issue of result.issues)logger_logger.error(` - ${issue.path?.map((p)=>p.key).join(".") || "root"}: ${issue.message}`);
43380
- return false;
43381
- }
43382
- return true;
43832
+ if (!result.success) return {
43833
+ ok: false,
43834
+ message: "anvil.yaml is invalid for Anvil",
43835
+ issues: result.issues.map((issue)=>({
43836
+ path: formatValibotIssuePath(issue),
43837
+ message: issue.message
43838
+ }))
43839
+ };
43840
+ const runtimeOptionIssues = validateRuntimeOptions(result.output.runtime_options, "runtime_options");
43841
+ if (runtimeOptionIssues.length > 0) return {
43842
+ ok: false,
43843
+ message: "anvil.yaml is invalid for Anvil",
43844
+ issues: runtimeOptionIssues
43845
+ };
43846
+ const serviceIssues = validateKnownServiceSources(result.output.services, "services");
43847
+ if (serviceIssues.length > 0) return {
43848
+ ok: false,
43849
+ message: "anvil.yaml is invalid for Anvil",
43850
+ issues: serviceIssues
43851
+ };
43852
+ const serviceConfigIssues = validateServiceConfigs(result.output.services, "services");
43853
+ if (serviceConfigIssues.length > 0) return {
43854
+ ok: false,
43855
+ message: "anvil.yaml is invalid for Anvil",
43856
+ issues: serviceConfigIssues
43857
+ };
43858
+ const scheduledTaskIssues = validateScheduledTasks(result.output.scheduled_tasks, "scheduled_tasks");
43859
+ if (scheduledTaskIssues.length > 0) return {
43860
+ ok: false,
43861
+ message: "anvil.yaml is invalid for Anvil",
43862
+ issues: scheduledTaskIssues
43863
+ };
43864
+ const dbIssues = validateDbSchema(result.output.db_schema, "db_schema");
43865
+ if (dbIssues.length > 0) return {
43866
+ ok: false,
43867
+ message: "anvil.yaml is invalid for Anvil",
43868
+ issues: dbIssues
43869
+ };
43870
+ return {
43871
+ ok: true
43872
+ };
43383
43873
  } catch (error) {
43384
- logger_logger.error(`anvil.yaml: YAML parse error: ${error}`);
43385
- return false;
43874
+ return {
43875
+ ok: false,
43876
+ message: "anvil.yaml is not valid YAML",
43877
+ issues: [
43878
+ {
43879
+ path: "",
43880
+ message: error instanceof Error ? error.message : String(error)
43881
+ }
43882
+ ]
43883
+ };
43884
+ }
43885
+ }
43886
+ function inferValidationTarget(filePath) {
43887
+ const normalizedPath = filePath.replace(/\\/g, "/");
43888
+ if ("anvil.yaml" === normalizedPath || normalizedPath.endsWith("/anvil.yaml")) return "anvil.yaml";
43889
+ const clientCodePrefix = "client_code/";
43890
+ if (normalizedPath.startsWith(clientCodePrefix) || normalizedPath.includes(`/${clientCodePrefix}`)) {
43891
+ const startIndex = normalizedPath.lastIndexOf(clientCodePrefix);
43892
+ const relativeToClientCode = normalizedPath.slice(startIndex + clientCodePrefix.length);
43893
+ if (relativeToClientCode.endsWith(".yaml")) return "form_template.yaml";
43386
43894
  }
43895
+ return null;
43896
+ }
43897
+ function resolveExistingPath(filePath) {
43898
+ const absolutePath = external_path_default().resolve(filePath);
43899
+ return external_fs_.existsSync(absolutePath) ? absolutePath : null;
43900
+ }
43901
+ function findAnvilAppRoot(filePath) {
43902
+ const existingPath = resolveExistingPath(filePath);
43903
+ if (!existingPath) return null;
43904
+ let currentDir = external_fs_.statSync(existingPath).isDirectory() ? existingPath : external_path_default().dirname(existingPath);
43905
+ let appRoot = null;
43906
+ while(true){
43907
+ if (external_fs_.existsSync(external_path_default().join(currentDir, "anvil.yaml"))) appRoot = currentDir;
43908
+ const parentDir = external_path_default().dirname(currentDir);
43909
+ if (parentDir === currentDir) return appRoot;
43910
+ currentDir = parentDir;
43911
+ }
43912
+ }
43913
+ function validatePath(filePath, yamlContent) {
43914
+ const target = inferValidationTarget(filePath);
43915
+ const existingPath = resolveExistingPath(filePath);
43916
+ const appRoot = findAnvilAppRoot(filePath);
43917
+ if (existingPath && !appRoot) return {
43918
+ ok: false,
43919
+ target: target ?? "unknown",
43920
+ message: "File is not inside an Anvil app",
43921
+ issues: [
43922
+ {
43923
+ path: "",
43924
+ message: "could not find an anvil.yaml app root for this file"
43925
+ }
43926
+ ]
43927
+ };
43928
+ if ("anvil.yaml" === target) {
43929
+ if (existingPath && appRoot && external_path_default().resolve(existingPath) !== external_path_default().join(appRoot, "anvil.yaml")) return {
43930
+ ok: false,
43931
+ target,
43932
+ message: "File is not the app root anvil.yaml",
43933
+ issues: [
43934
+ {
43935
+ path: "",
43936
+ message: `expected ${external_path_default().join(appRoot, "anvil.yaml")}`
43937
+ }
43938
+ ]
43939
+ };
43940
+ const result = validateAnvilYaml(yamlContent);
43941
+ return result.ok ? {
43942
+ ok: true,
43943
+ target
43944
+ } : {
43945
+ ...result,
43946
+ target
43947
+ };
43948
+ }
43949
+ if ("form_template.yaml" === target) {
43950
+ if (existingPath && appRoot) {
43951
+ const clientCodeRoot = external_path_default().join(appRoot, "client_code");
43952
+ const relativeToClientCode = external_path_default().relative(clientCodeRoot, existingPath);
43953
+ const isInsideClientCode = relativeToClientCode.length > 0 && !relativeToClientCode.startsWith("..") && !external_path_default().isAbsolute(relativeToClientCode);
43954
+ if (!isInsideClientCode || !existingPath.endsWith(".yaml")) return {
43955
+ ok: false,
43956
+ target,
43957
+ message: "File is not a client_code YAML form",
43958
+ issues: [
43959
+ {
43960
+ path: "",
43961
+ message: `expected a .yaml file under ${clientCodeRoot}`
43962
+ }
43963
+ ]
43964
+ };
43965
+ }
43966
+ const result = validateFormTemplate(yamlContent);
43967
+ return result.ok ? {
43968
+ ok: true,
43969
+ target
43970
+ } : {
43971
+ ...result,
43972
+ target
43973
+ };
43974
+ }
43975
+ return {
43976
+ ok: false,
43977
+ target: "unknown",
43978
+ message: "No validator for this path",
43979
+ issues: [
43980
+ {
43981
+ path: "",
43982
+ message: "supported paths are anvil.yaml, client_code/**/form_template.yaml, and client_code/**/*.yaml"
43983
+ }
43984
+ ]
43985
+ };
43387
43986
  }
43388
43987
  function normalizeClientCodePath(relativePath) {
43389
43988
  return relativePath.replace(/\\/g, "/");
@@ -43423,10 +44022,15 @@ var __webpack_exports__ = {};
43423
44022
  try {
43424
44023
  const content = await readFileContent(repoPath, relativePath, stagedOnly);
43425
44024
  if ("yaml" === format) {
43426
- if (!validateFormTemplate(content)) return {
43427
- ok: false,
43428
- reason: "package" === kind ? "Invalid form_template.yaml - validation failed" : "Invalid form yaml - validation failed"
43429
- };
44025
+ const validationResult = validateFormTemplate(content);
44026
+ if (!validationResult.ok) {
44027
+ const firstIssue = validationResult.issues[0];
44028
+ const issueSummary = firstIssue ? `${formatValidationPath(firstIssue.path)}: ${firstIssue.message}` : void 0;
44029
+ return {
44030
+ ok: false,
44031
+ reason: issueSummary ? `${validationResult.message}. ${issueSummary}` : validationResult.message
44032
+ };
44033
+ }
43430
44034
  const parsed = jsYaml.load(content);
43431
44035
  const template = {
43432
44036
  ...parsed,
@@ -44100,10 +44704,11 @@ var __webpack_exports__ = {};
44100
44704
  });
44101
44705
  }
44102
44706
  function buildFormDataFromTemplate(template, html, options) {
44707
+ const { class_name: _templateClassName, code: _templateCode, is_package: _templateIsPackage, ...templateRest } = template && "object" == typeof template ? template : {};
44103
44708
  const formData = {
44709
+ ...templateRest,
44104
44710
  class_name: options.className,
44105
44711
  code: options.code,
44106
- ...template,
44107
44712
  is_package: options.isPackage
44108
44713
  };
44109
44714
  if (void 0 !== html) {
@@ -44313,7 +44918,8 @@ var __webpack_exports__ = {};
44313
44918
  requirements: currentRequirements
44314
44919
  }
44315
44920
  };
44316
- if (!validateAnvilYaml(yamlContent)) throw new Error("anvil.yaml validation failed - see errors above");
44921
+ const validationResult = validateAnvilYaml(yamlContent);
44922
+ if (!validationResult.ok) throw new Error("anvil.yaml validation failed - see errors above");
44317
44923
  const changes = [];
44318
44924
  for (const [key, value] of Object.entries(parsedYaml))if (!previousYaml || !deepEqual(previousYaml[key], value)) changes.push({
44319
44925
  key,
@@ -44808,6 +45414,19 @@ var __webpack_exports__ = {};
44808
45414
  };
44809
45415
  }
44810
45416
  }
45417
+ function stripNonSemanticYamlFields(yamlFile, parsed) {
45418
+ const normalized = {
45419
+ ...parsed ?? {}
45420
+ };
45421
+ delete normalized.is_package;
45422
+ const normalizedPath = yamlFile.replace(/\\/g, "/");
45423
+ const isFormTemplate = normalizedPath.startsWith("client_code/") && (normalizedPath.endsWith("/form_template.yaml") || /^client_code\/[^/]+\.ya?ml$/i.test(normalizedPath) && !normalizedPath.endsWith("anvil.yaml"));
45424
+ if (isFormTemplate) {
45425
+ delete normalized.class_name;
45426
+ delete normalized.code;
45427
+ }
45428
+ return normalized;
45429
+ }
44811
45430
  class SyncManager extends Emitter {
44812
45431
  config;
44813
45432
  syncInProgress = false;
@@ -44928,8 +45547,8 @@ var __webpack_exports__ = {};
44928
45547
  }
44929
45548
  const workingParsed = load(workingContent);
44930
45549
  const headParsed = load(headContent);
44931
- const { is_package: _w, ...workingForCompare } = workingParsed;
44932
- const { is_package: _h, ...headForCompare } = headParsed;
45550
+ const workingForCompare = stripNonSemanticYamlFields(yamlFile, workingParsed);
45551
+ const headForCompare = stripNonSemanticYamlFields(yamlFile, headParsed);
44933
45552
  if (deepEqual(workingForCompare, headForCompare)) {
44934
45553
  logger_logger.verbose(chalk_source.gray(` Discarding formatting-only change: ${yamlFile}`));
44935
45554
  await this.config.gitService.checkout([
@@ -45672,7 +46291,7 @@ var __webpack_exports__ = {};
45672
46291
  const execFile = (0, external_node_util_namespaceObject.promisify)(external_node_child_process_namespaceObject.execFile);
45673
46292
  const open_dirname = external_node_path_.dirname((0, external_node_url_namespaceObject.fileURLToPath)(__rslib_import_meta_url__));
45674
46293
  const localXdgOpenPath = external_node_path_.join(open_dirname, 'xdg-open');
45675
- const { platform, arch } = external_node_process_namespaceObject;
46294
+ const { platform: open_platform, arch } = external_node_process_namespaceObject;
45676
46295
  async function getWindowsDefaultBrowserFromWsl() {
45677
46296
  const powershellPath = await powerShellPath();
45678
46297
  const rawCommand = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
@@ -45765,13 +46384,13 @@ var __webpack_exports__ = {};
45765
46384
  let command;
45766
46385
  const cliArguments = [];
45767
46386
  const childProcessOptions = {};
45768
- if ('darwin' === platform) {
46387
+ if ('darwin' === open_platform) {
45769
46388
  command = 'open';
45770
46389
  if (options.wait) cliArguments.push('--wait-apps');
45771
46390
  if (options.background) cliArguments.push('--background');
45772
46391
  if (options.newInstance) cliArguments.push('--new');
45773
46392
  if (app) cliArguments.push('-a', app);
45774
- } else if ('win32' !== platform && (!is_wsl || isInsideContainer() || app)) {
46393
+ } else if ('win32' !== open_platform && (!is_wsl || isInsideContainer() || app)) {
45775
46394
  if (app) command = app;
45776
46395
  else {
45777
46396
  const isBundled = !open_dirname || '/' === open_dirname;
@@ -45780,7 +46399,7 @@ var __webpack_exports__ = {};
45780
46399
  await external_node_fs_promises_namespaceObject.access(localXdgOpenPath, external_node_fs_promises_namespaceObject.constants.X_OK);
45781
46400
  exeLocalXdgOpen = true;
45782
46401
  } catch {}
45783
- const useSystemXdgOpen = external_node_process_namespaceObject.versions.electron ?? ('android' === platform || isBundled || !exeLocalXdgOpen);
46402
+ const useSystemXdgOpen = external_node_process_namespaceObject.versions.electron ?? ('android' === open_platform || isBundled || !exeLocalXdgOpen);
45784
46403
  command = useSystemXdgOpen ? 'xdg-open' : localXdgOpenPath;
45785
46404
  }
45786
46405
  if (appArguments.length > 0) cliArguments.push(...appArguments);
@@ -45806,7 +46425,7 @@ var __webpack_exports__ = {};
45806
46425
  }
45807
46426
  options.target = external_node_buffer_namespaceObject.Buffer.from(encodedArguments.join(' '), 'utf16le').toString('base64');
45808
46427
  }
45809
- if ('darwin' === platform && appArguments.length > 0) cliArguments.push('--args', ...appArguments);
46428
+ if ('darwin' === open_platform && appArguments.length > 0) cliArguments.push('--args', ...appArguments);
45810
46429
  if (options.target) cliArguments.push(options.target);
45811
46430
  const subprocess = external_node_child_process_namespaceObject.spawn(command, cliArguments, childProcessOptions);
45812
46431
  if (options.wait) return new Promise((resolve, reject)=>{
@@ -45832,9 +46451,9 @@ var __webpack_exports__ = {};
45832
46451
  if (!archBinary) throw new Error(`${arch} is not supported`);
45833
46452
  return archBinary;
45834
46453
  }
45835
- function detectPlatformBinary({ [platform]: platformBinary }, { wsl }) {
46454
+ function detectPlatformBinary({ [open_platform]: platformBinary }, { wsl }) {
45836
46455
  if (wsl && is_wsl) return detectArchBinary(wsl);
45837
- if (!platformBinary) throw new Error(`${platform} is not supported`);
46456
+ if (!platformBinary) throw new Error(`${open_platform} is not supported`);
45838
46457
  return detectArchBinary(platformBinary);
45839
46458
  }
45840
46459
  const open_apps = {};
@@ -46306,6 +46925,33 @@ var __webpack_exports__ = {};
46306
46925
  function getUsernameConfigKey(appId) {
46307
46926
  return `anvil.auth.${appId}.username`;
46308
46927
  }
46928
+ function shellQuote(value) {
46929
+ return `'${value.replace(/'/g, "'\\''")}'`;
46930
+ }
46931
+ function shellQuoteDouble(value) {
46932
+ return `"${value.replace(/(["$`])/g, "\\$1")}"`;
46933
+ }
46934
+ function getDefaultCliPath(options) {
46935
+ const servicesDir = options?.servicesDir ?? __dirname;
46936
+ const pathExists = options?.pathExists ?? external_fs_default().existsSync;
46937
+ const candidates = [
46938
+ external_path_default().resolve(servicesDir, "..", "cli.js"),
46939
+ external_path_default().resolve(servicesDir, "..", "cli.ts")
46940
+ ];
46941
+ return candidates.find((candidate)=>pathExists(candidate));
46942
+ }
46943
+ function getGitCredentialHelperCommand(options) {
46944
+ const platform = options?.platform ?? process.platform;
46945
+ const execPath = options?.execPath ?? process.execPath;
46946
+ const cliPath = options?.cliPath ?? getDefaultCliPath() ?? process.argv[1];
46947
+ if (!execPath || !cliPath) return "!anvil git-credential";
46948
+ if ("win32" === platform) {
46949
+ const resolvedExecPath = external_path_default().win32.resolve(execPath);
46950
+ const resolvedCliPath = external_path_default().win32.resolve(cliPath);
46951
+ return `!${shellQuoteDouble(resolvedExecPath)} ${shellQuoteDouble(resolvedCliPath)} git-credential`;
46952
+ }
46953
+ return `!${shellQuote(external_path_default().resolve(execPath))} ${shellQuote(external_path_default().resolve(cliPath))} git-credential`;
46954
+ }
46309
46955
  async function git_auth_setAppAuthBinding(repoPath, appId, binding) {
46310
46956
  const git = esm_default(repoPath);
46311
46957
  if (binding.url) await git.raw([
@@ -46351,7 +46997,7 @@ var __webpack_exports__ = {};
46351
46997
  "--local",
46352
46998
  "--add",
46353
46999
  `credential.${scope}.helper`,
46354
- "!anvil git-credential"
47000
+ getGitCredentialHelperCommand()
46355
47001
  ]);
46356
47002
  await git.raw([
46357
47003
  "config",
@@ -47387,7 +48033,7 @@ var __webpack_exports__ = {};
47387
48033
  key: (text)=>yoctocolors_cjs.cyan(yoctocolors_cjs.bold(`<${text}>`))
47388
48034
  }
47389
48035
  };
47390
- function isPlainObject(value) {
48036
+ function make_theme_isPlainObject(value) {
47391
48037
  if ('object' != typeof value || null === value) return false;
47392
48038
  let proto = value;
47393
48039
  while(null !== Object.getPrototypeOf(proto))proto = Object.getPrototypeOf(proto);
@@ -47397,7 +48043,7 @@ var __webpack_exports__ = {};
47397
48043
  const output = {};
47398
48044
  for (const obj of objects)for (const [key, value] of Object.entries(obj)){
47399
48045
  const prevValue = output[key];
47400
- output[key] = isPlainObject(prevValue) && isPlainObject(value) ? deepMerge(prevValue, value) : value;
48046
+ output[key] = make_theme_isPlainObject(prevValue) && make_theme_isPlainObject(value) ? deepMerge(prevValue, value) : value;
47401
48047
  }
47402
48048
  return output;
47403
48049
  }
@@ -49704,6 +50350,7 @@ var __webpack_exports__ = {};
49704
50350
  return session;
49705
50351
  }
49706
50352
  })();
50353
+ exports.AnvilYamlValidationResult = __webpack_exports__.AnvilYamlValidationResult;
49707
50354
  exports.AppIdCandidate = __webpack_exports__.AppIdCandidate;
49708
50355
  exports.AppIdWithContext = __webpack_exports__.AppIdWithContext;
49709
50356
  exports.BranchSyncStatus = __webpack_exports__.BranchSyncStatus;
@@ -49712,6 +50359,7 @@ exports.CheckoutCloneOptions = __webpack_exports__.CheckoutCloneOptions;
49712
50359
  exports.CheckoutExecutionDeps = __webpack_exports__.CheckoutExecutionDeps;
49713
50360
  exports.CheckoutOptions = __webpack_exports__.CheckoutOptions;
49714
50361
  exports.DeviceAuthorizationResponse = __webpack_exports__.DeviceAuthorizationResponse;
50362
+ exports.FormTemplateValidationResult = __webpack_exports__.FormTemplateValidationResult;
49715
50363
  exports.LoginResult = __webpack_exports__.LoginResult;
49716
50364
  exports.LogoutResult = __webpack_exports__.LogoutResult;
49717
50365
  exports.OAuthTokenResponse = __webpack_exports__.OAuthTokenResponse;
@@ -49721,6 +50369,9 @@ exports.SettableConfigKey = __webpack_exports__.SettableConfigKey;
49721
50369
  exports.StoredTokens = __webpack_exports__.StoredTokens;
49722
50370
  exports.TokenData = __webpack_exports__.TokenData;
49723
50371
  exports.ValidateAppIdResponse = __webpack_exports__.ValidateAppIdResponse;
50372
+ exports.ValidatePathResult = __webpack_exports__.ValidatePathResult;
50373
+ exports.ValidationIssue = __webpack_exports__.ValidationIssue;
50374
+ exports.ValidationTarget = __webpack_exports__.ValidationTarget;
49724
50375
  exports.checkUncommittedChanges = __webpack_exports__.checkUncommittedChanges;
49725
50376
  exports.deleteConfig = __webpack_exports__.deleteConfig;
49726
50377
  exports.detectAppIdsByCommitLookup = __webpack_exports__.detectAppIdsByCommitLookup;
@@ -49729,6 +50380,7 @@ exports.ensureCheckoutAuthToken = __webpack_exports__.ensureCheckoutAuthToken;
49729
50380
  exports.executeCheckout = __webpack_exports__.executeCheckout;
49730
50381
  exports.filterCandidates = __webpack_exports__.filterCandidates;
49731
50382
  exports.formatCandidateLabel = __webpack_exports__.formatCandidateLabel;
50383
+ exports.formatValidationPath = __webpack_exports__.formatValidationPath;
49732
50384
  exports.getAccountsForUrl = __webpack_exports__.getAccountsForUrl;
49733
50385
  exports.getAllConfig = __webpack_exports__.getAllConfig;
49734
50386
  exports.getAvailableAnvilUrls = __webpack_exports__.getAvailableAnvilUrls;
@@ -49769,12 +50421,16 @@ exports.saveUpdates = __webpack_exports__.saveUpdates;
49769
50421
  exports.setConfig = __webpack_exports__.setConfig;
49770
50422
  exports.syncToLatest = __webpack_exports__.syncToLatest;
49771
50423
  exports.validateAnvilApp = __webpack_exports__.validateAnvilApp;
50424
+ exports.validateAnvilYaml = __webpack_exports__.validateAnvilYaml;
49772
50425
  exports.validateAppId = __webpack_exports__.validateAppId;
49773
50426
  exports.validateBranchSyncStatus = __webpack_exports__.validateBranchSyncStatus;
49774
50427
  exports.validateCheckoutDestination = __webpack_exports__.validateCheckoutDestination;
50428
+ exports.validateFormTemplate = __webpack_exports__.validateFormTemplate;
50429
+ exports.validatePath = __webpack_exports__.validatePath;
49775
50430
  exports.verifyAuth = __webpack_exports__.verifyAuth;
49776
50431
  exports.watch = __webpack_exports__.watch;
49777
50432
  for(var __rspack_i in __webpack_exports__)if (-1 === [
50433
+ "AnvilYamlValidationResult",
49778
50434
  "AppIdCandidate",
49779
50435
  "AppIdWithContext",
49780
50436
  "BranchSyncStatus",
@@ -49783,6 +50439,7 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
49783
50439
  "CheckoutExecutionDeps",
49784
50440
  "CheckoutOptions",
49785
50441
  "DeviceAuthorizationResponse",
50442
+ "FormTemplateValidationResult",
49786
50443
  "LoginResult",
49787
50444
  "LogoutResult",
49788
50445
  "OAuthTokenResponse",
@@ -49792,6 +50449,9 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
49792
50449
  "StoredTokens",
49793
50450
  "TokenData",
49794
50451
  "ValidateAppIdResponse",
50452
+ "ValidatePathResult",
50453
+ "ValidationIssue",
50454
+ "ValidationTarget",
49795
50455
  "checkUncommittedChanges",
49796
50456
  "deleteConfig",
49797
50457
  "detectAppIdsByCommitLookup",
@@ -49800,6 +50460,7 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
49800
50460
  "executeCheckout",
49801
50461
  "filterCandidates",
49802
50462
  "formatCandidateLabel",
50463
+ "formatValidationPath",
49803
50464
  "getAccountsForUrl",
49804
50465
  "getAllConfig",
49805
50466
  "getAvailableAnvilUrls",
@@ -49840,9 +50501,12 @@ for(var __rspack_i in __webpack_exports__)if (-1 === [
49840
50501
  "setConfig",
49841
50502
  "syncToLatest",
49842
50503
  "validateAnvilApp",
50504
+ "validateAnvilYaml",
49843
50505
  "validateAppId",
49844
50506
  "validateBranchSyncStatus",
49845
50507
  "validateCheckoutDestination",
50508
+ "validateFormTemplate",
50509
+ "validatePath",
49846
50510
  "verifyAuth",
49847
50511
  "watch"
49848
50512
  ].indexOf(__rspack_i)) exports[__rspack_i] = __webpack_exports__[__rspack_i];