@verentis/cli 0.2.2 → 0.2.3

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
@@ -893,14 +893,49 @@ function validateManifest(manifest) {
893
893
  if (!manifestPermissions(manifest).length) warning("spec.permissions is empty \u2014 the run token will carry no VFS scopes");
894
894
  }
895
895
  if (kind === "Application") {
896
- if (!spec.entry && !spec["entry-points"]?.length) {
897
- error("applications need spec.entry or spec.entry-points[]");
896
+ const hasIframe = !!spec.entry || !!spec["entry-points"]?.length;
897
+ const hasInstall = Array.isArray(spec.install) && spec.install.length > 0;
898
+ const hasScopes = Array.isArray(spec.scopes) && spec.scopes.length > 0;
899
+ if (!hasIframe && !hasInstall && !hasScopes) {
900
+ error(
901
+ "an Application must declare at least one contribution: spec.entry / spec.entry-points[] (iframe UI), spec.install[] (installed files), or spec.scopes[] (identity)"
902
+ );
898
903
  }
899
904
  }
905
+ validateInstallDirectives(spec.install, issues);
900
906
  const packaging = manifest.packaging ?? {};
901
907
  if (!packaging.publisher) warning("packaging.publisher is not set \u2014 `verentis pack`/`publish` will refuse the package");
902
908
  return issues;
903
909
  }
910
+ function validateInstallDirectives(install, issues) {
911
+ if (install === void 0) return;
912
+ const error = (message) => issues.push({ level: "error", message });
913
+ if (!Array.isArray(install)) {
914
+ error("spec.install must be a list of install directives");
915
+ return;
916
+ }
917
+ install.forEach((directive, index) => {
918
+ const at = `spec.install[${index}]`;
919
+ if (!directive || typeof directive !== "object") {
920
+ error(`${at} must be an object with 'from' and 'to'`);
921
+ return;
922
+ }
923
+ if (!directive.from || typeof directive.from !== "string") {
924
+ error(`${at}.from is required (a path/glob relative to the package payload)`);
925
+ } else if (directive.from.startsWith("/") || directive.from.split("/").includes("..")) {
926
+ error(`${at}.from must be a relative path inside the package payload (no leading '/' or '..')`);
927
+ }
928
+ if (!directive.to || typeof directive.to !== "string") {
929
+ error(`${at}.to is required (a workspace-absolute destination path)`);
930
+ } else {
931
+ if (!directive.to.startsWith("/")) error(`${at}.to must be a workspace-absolute path (start with '/')`);
932
+ if (directive.to.split("/").includes("..")) error(`${at}.to must not contain '..'`);
933
+ }
934
+ if (directive.mode !== void 0 && directive.mode !== "seed" && directive.mode !== "managed") {
935
+ error(`${at}.mode must be 'seed' or 'managed' (got '${directive.mode}')`);
936
+ }
937
+ });
938
+ }
904
939
  var KIND_MAP = {
905
940
  application: "Application",
906
941
  executionengine: "ExecutionEngine",
@@ -1974,9 +2009,21 @@ async function resolvePayloadFiles(projectDir, manifestPath, manifest) {
1974
2009
  function defaultIncludes(manifest) {
1975
2010
  const sources = /* @__PURE__ */ new Set();
1976
2011
  collectSchemaSources(manifest, sources);
2012
+ collectInstallSources(manifest, sources);
1977
2013
  if (sources.size === 0) return [];
1978
2014
  return [...sources];
1979
2015
  }
2016
+ function collectInstallSources(manifest, sources) {
2017
+ const spec = manifest.spec;
2018
+ const install = spec?.install;
2019
+ if (!Array.isArray(install)) return;
2020
+ for (const directive of install) {
2021
+ const from = directive?.from;
2022
+ if (typeof from === "string" && from.length > 0 && !from.startsWith("/")) {
2023
+ sources.add(from);
2024
+ }
2025
+ }
2026
+ }
1980
2027
  function collectSchemaSources(node, sources) {
1981
2028
  if (Array.isArray(node)) {
1982
2029
  for (const item of node) collectSchemaSources(item, sources);