@anvil-works/anvil-cli 0.8.0-canary.0 → 0.8.0-canary.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"SavePathRouter.d.ts","sourceRoot":"","sources":["../src/SavePathRouter.ts"],"names":[],"mappings":"AAMA,OAAO,EAGH,KAAK,uBAAuB,EAE/B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAmB,MAAM,cAAc,CAAC;AAMlE,KAAK,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;AAG3B,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,MAAM,QAAQ,GAAG,uBAAuB,CAAC;AAE/C,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACnB;AASD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEhE,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjH,MAAM,WAAW,YAAY;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AA2VD;;;GAGG;AACH,wBAAgB,sBAAsB,CAClC,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAC9F,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAgEtF;AAED,wBAAsB,eAAe,CACjC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,YAAY,GACtB,OAAO,CAAC,UAAU,GAAG,UAAU,EAAE,CAAC,CAqBpC;AA6yBD;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACrC,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,GAC1C,OAAO,CAAC,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,GAAG,CAAA;CAAE,CAAC,CAAC,CAiE7C"}
1
+ {"version":3,"file":"SavePathRouter.d.ts","sourceRoot":"","sources":["../src/SavePathRouter.ts"],"names":[],"mappings":"AAMA,OAAO,EAGH,KAAK,uBAAuB,EAE/B,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,iBAAiB,EAAmB,MAAM,cAAc,CAAC;AAMlE,KAAK,QAAQ,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;AAG3B,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,MAAM,QAAQ,GAAG,uBAAuB,CAAC;AAE/C,MAAM,WAAW,SAAS;IACtB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACnB;AASD,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAEhE,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAC;IAAC,OAAO,EAAE,GAAG,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEjH,MAAM,WAAW,YAAY;IACzB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,iBAAiB,CAAC;IAC9B,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,eAAe;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAwWD;;;GAGG;AACH,wBAAgB,sBAAsB,CAClC,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,GAC9F,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,QAAQ,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,CAgEtF;AAED,wBAAsB,eAAe,CACjC,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,YAAY,GACtB,OAAO,CAAC,UAAU,GAAG,UAAU,EAAE,CAAC,CAqBpC;AA8zBD;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACrC,QAAQ,EAAE,MAAM,EAChB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,IAAI,GAC1C,OAAO,CAAC,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,GAAG,CAAA;CAAE,CAAC,CAAC,CAiE7C"}
package/dist/cli.js CHANGED
@@ -16256,15 +16256,73 @@ Promise.resolve(executeGitCredentialOperation(process.argv[2] || "get", {
16256
16256
  message
16257
16257
  });
16258
16258
  }
16259
+ function offsetToLocation(source, offset) {
16260
+ const safeOffset = Math.max(0, Math.min(offset, source.length));
16261
+ let line = 1;
16262
+ let column = 1;
16263
+ for(let index = 0; index < safeOffset; index += 1){
16264
+ const char = source[index];
16265
+ if ("\n" === char) {
16266
+ line += 1;
16267
+ column = 1;
16268
+ } else column += 1;
16269
+ }
16270
+ return {
16271
+ line,
16272
+ column,
16273
+ offset: safeOffset
16274
+ };
16275
+ }
16276
+ function warningLocationFields(source, bodyStartOffset, warning) {
16277
+ if ("number" != typeof warning.from) return {};
16278
+ const start = offsetToLocation(source, bodyStartOffset + warning.from);
16279
+ const fields = {
16280
+ line: start.line,
16281
+ column: start.column,
16282
+ offset: start.offset
16283
+ };
16284
+ if ("number" == typeof warning.to) {
16285
+ const end = offsetToLocation(source, bodyStartOffset + warning.to);
16286
+ fields.endLine = end.line;
16287
+ fields.endColumn = end.column;
16288
+ fields.endOffset = end.offset;
16289
+ }
16290
+ return fields;
16291
+ }
16292
+ function parserWarnings(parsed, source, bodyStartOffset) {
16293
+ const warnings = parsed.warnings ?? [];
16294
+ return warnings.map((warning)=>({
16295
+ path: warning.path,
16296
+ message: warning.message,
16297
+ ...warning.code ? {
16298
+ code: warning.code
16299
+ } : {},
16300
+ ...warning.name ? {
16301
+ name: warning.name
16302
+ } : {},
16303
+ ...warning.attrName ? {
16304
+ attrName: warning.attrName
16305
+ } : {},
16306
+ ...warning.tagName ? {
16307
+ tagName: warning.tagName
16308
+ } : {},
16309
+ ...warning.eventName ? {
16310
+ eventName: warning.eventName
16311
+ } : {},
16312
+ ...warningLocationFields(source, bodyStartOffset, warning)
16313
+ }));
16314
+ }
16259
16315
  function splitHtmlFormTemplateFrontmatter(htmlContent) {
16260
16316
  const match = htmlContent.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
16261
16317
  if (!match) return {
16262
16318
  frontmatter: null,
16263
- body: htmlContent
16319
+ body: htmlContent,
16320
+ bodyStartOffset: 0
16264
16321
  };
16265
16322
  return {
16266
16323
  frontmatter: match[1],
16267
- body: htmlContent.slice(match[0].length)
16324
+ body: htmlContent.slice(match[0].length),
16325
+ bodyStartOffset: match[0].length
16268
16326
  };
16269
16327
  }
16270
16328
  function validateHtmlFrontmatter(frontmatterYaml) {
@@ -16295,8 +16353,8 @@ Promise.resolve(executeGitCredentialOperation(process.argv[2] || "get", {
16295
16353
  function validateParsedHtmlTemplate(parsed) {
16296
16354
  return validateFormTemplateData(parsed);
16297
16355
  }
16298
- function validateFormTemplateHtml(htmlContent) {
16299
- const { frontmatter, body } = splitHtmlFormTemplateFrontmatter(htmlContent);
16356
+ function validateFormTemplateHtml(htmlContent, parseHtml = form_template_parser_namespaceObject.parseSerializedHtml) {
16357
+ const { frontmatter, body, bodyStartOffset } = splitHtmlFormTemplateFrontmatter(htmlContent);
16300
16358
  if (null !== frontmatter) {
16301
16359
  const frontmatterIssues = validateHtmlFrontmatter(frontmatter);
16302
16360
  if (frontmatterIssues.length > 0) return {
@@ -16307,7 +16365,9 @@ Promise.resolve(executeGitCredentialOperation(process.argv[2] || "get", {
16307
16365
  }
16308
16366
  let parsed;
16309
16367
  try {
16310
- parsed = (0, form_template_parser_namespaceObject.parseSerializedHtml)(body);
16368
+ parsed = parseHtml(body, {
16369
+ warnings: true
16370
+ });
16311
16371
  } catch (error) {
16312
16372
  return {
16313
16373
  ok: false,
@@ -16320,13 +16380,20 @@ Promise.resolve(executeGitCredentialOperation(process.argv[2] || "get", {
16320
16380
  ]
16321
16381
  };
16322
16382
  }
16383
+ const warnings = parserWarnings(parsed, htmlContent, bodyStartOffset);
16323
16384
  const issues = validateParsedHtmlTemplate(parsed);
16324
16385
  if (issues.length > 0) return {
16325
16386
  ok: false,
16326
16387
  message: "form_template.html is invalid for Anvil",
16327
- issues
16328
- };
16329
- return {
16388
+ issues,
16389
+ ...warnings.length > 0 ? {
16390
+ warnings
16391
+ } : {}
16392
+ };
16393
+ return warnings.length > 0 ? {
16394
+ ok: true,
16395
+ warnings
16396
+ } : {
16330
16397
  ok: true
16331
16398
  };
16332
16399
  }
@@ -16596,6 +16663,16 @@ print(json.dumps({"issues": issues}))
16596
16663
  message
16597
16664
  });
16598
16665
  }
16666
+ function validPathResult(target, warnings) {
16667
+ return warnings && warnings.length > 0 ? {
16668
+ ok: true,
16669
+ target,
16670
+ warnings
16671
+ } : {
16672
+ ok: true,
16673
+ target
16674
+ };
16675
+ }
16599
16676
  function formatValidationPath(path) {
16600
16677
  return path || "root";
16601
16678
  }
@@ -16773,6 +16850,9 @@ print(json.dumps({"issues": issues}))
16773
16850
  if (void 0 === services || !Array.isArray(services)) return issues;
16774
16851
  services.forEach((service, index)=>{
16775
16852
  if (!validators_isPlainObject(service) || "/runtime/services/anvil/users.yml" !== service.source) return;
16853
+ if (validators_isPlainObject(service.server_config) && void 0 !== service.server_config.user_table) {
16854
+ if ("string" != typeof service.server_config.user_table && "number" != typeof service.server_config.user_table) validators_pushIssue(issues, `${path}[${index}].server_config.user_table`, "must be a table Python name string or legacy table id number");
16855
+ } else validators_pushIssue(issues, `${path}[${index}].server_config.user_table`, 'is required for the Users service; this is usually "users"');
16776
16856
  if (!validators_isPlainObject(service.client_config)) return;
16777
16857
  if (true === service.client_config.allow_remember_me && void 0 === service.client_config.remember_me_days) validators_pushIssue(issues, `${path}[${index}].client_config.remember_me_days`, "must be set if allow_remember_me is true");
16778
16858
  });
@@ -16964,10 +17044,7 @@ print(json.dumps({"issues": issues}))
16964
17044
  ]
16965
17045
  };
16966
17046
  const result = validateAnvilYaml(fileContent);
16967
- return result.ok ? {
16968
- ok: true,
16969
- target
16970
- } : {
17047
+ return result.ok ? validPathResult(target, result.warnings) : {
16971
17048
  ...result,
16972
17049
  target
16973
17050
  };
@@ -16990,10 +17067,7 @@ print(json.dumps({"issues": issues}))
16990
17067
  };
16991
17068
  }
16992
17069
  const result = validateFormTemplate(fileContent);
16993
- return result.ok ? {
16994
- ok: true,
16995
- target
16996
- } : {
17070
+ return result.ok ? validPathResult(target, result.warnings) : {
16997
17071
  ...result,
16998
17072
  target
16999
17073
  };
@@ -17016,10 +17090,7 @@ print(json.dumps({"issues": issues}))
17016
17090
  };
17017
17091
  }
17018
17092
  const result = validateFormTemplateHtml(fileContent);
17019
- return result.ok ? {
17020
- ok: true,
17021
- target
17022
- } : {
17093
+ return result.ok ? validPathResult(target, result.warnings) : {
17023
17094
  ...result,
17024
17095
  target
17025
17096
  };
@@ -17045,10 +17116,7 @@ print(json.dumps({"issues": issues}))
17045
17116
  };
17046
17117
  }
17047
17118
  const result = validatePython(filePath, fileContent, appRoot);
17048
- return result.ok ? {
17049
- ok: true,
17050
- target
17051
- } : {
17119
+ return result.ok ? validPathResult(target, result.warnings) : {
17052
17120
  ...result,
17053
17121
  target
17054
17122
  };
@@ -17068,6 +17136,10 @@ print(json.dumps({"issues": issues}))
17068
17136
  function normalizeClientCodePath(relativePath) {
17069
17137
  return relativePath.replace(/\\/g, "/");
17070
17138
  }
17139
+ function isRootCodePackageMarkerPath(relativePath) {
17140
+ const normalized = relativePath.replace(/\\/g, "/");
17141
+ return "client_code/__init__.py" === normalized || "server_code/__init__.py" === normalized;
17142
+ }
17071
17143
  function isServerRequirementsPath(relativePath) {
17072
17144
  return "server_code/requirements.txt" === relativePath.replace(/\\/g, "/");
17073
17145
  }
@@ -17163,8 +17235,12 @@ print(json.dumps({"issues": issues}))
17163
17235
  const parts = relativePath.split("/");
17164
17236
  if (2 === parts.length) return "scripts";
17165
17237
  }
17166
- if (relativePath.startsWith("server_code/") && relativePath.endsWith(".py")) return "server_modules";
17238
+ if (relativePath.startsWith("server_code/") && relativePath.endsWith(".py")) {
17239
+ if (isRootCodePackageMarkerPath(relativePath)) return null;
17240
+ return "server_modules";
17241
+ }
17167
17242
  if (relativePath.startsWith("client_code/") && relativePath.endsWith(".py")) {
17243
+ if (isRootCodePackageMarkerPath(relativePath)) return null;
17168
17244
  const isPackageInit = relativePath.endsWith("__init__.py");
17169
17245
  const kind = isPackageInit ? "package" : "module";
17170
17246
  const className = extractPythonName(relativePath);
@@ -17379,11 +17455,11 @@ print(json.dumps({"issues": issues}))
17379
17455
  handle: handleScriptsChange
17380
17456
  },
17381
17457
  {
17382
- matches: (relativePath)=>relativePath.startsWith("server_code/") && relativePath.endsWith(".py"),
17458
+ matches: (relativePath)=>relativePath.startsWith("server_code/") && relativePath.endsWith(".py") && !isRootCodePackageMarkerPath(relativePath),
17383
17459
  handle: handleServerCodeChange
17384
17460
  },
17385
17461
  {
17386
- matches: (relativePath)=>relativePath.startsWith("client_code/") && relativePath.endsWith(".py"),
17462
+ matches: (relativePath)=>relativePath.startsWith("client_code/") && relativePath.endsWith(".py") && !isRootCodePackageMarkerPath(relativePath),
17387
17463
  handle: handleClientCodeChange
17388
17464
  },
17389
17465
  {
@@ -17919,7 +17995,7 @@ print(json.dumps({"issues": issues}))
17919
17995
  const DELETION_ROUTES = [
17920
17996
  {
17921
17997
  matches: (relativePath, editorYaml)=>{
17922
- if (!relativePath.startsWith("client_code/") || !relativePath.endsWith(".py")) return false;
17998
+ if (!relativePath.startsWith("client_code/") || !relativePath.endsWith(".py") || isRootCodePackageMarkerPath(relativePath)) return false;
17923
17999
  const className = extractPythonName(relativePath);
17924
18000
  return editorYaml.hasId("forms", className);
17925
18001
  },
@@ -17931,7 +18007,7 @@ print(json.dumps({"issues": issues}))
17931
18007
  },
17932
18008
  {
17933
18009
  matches: (relativePath, editorYaml)=>{
17934
- if (!relativePath.startsWith("client_code/") || !relativePath.endsWith(".py")) return false;
18010
+ if (!relativePath.startsWith("client_code/") || !relativePath.endsWith(".py") || isRootCodePackageMarkerPath(relativePath)) return false;
17935
18011
  const className = extractPythonName(relativePath);
17936
18012
  return !editorYaml.hasId("forms", className);
17937
18013
  },
@@ -17954,7 +18030,7 @@ print(json.dumps({"issues": issues}))
17954
18030
  ]
17955
18031
  },
17956
18032
  {
17957
- matches: (relativePath)=>relativePath.startsWith("server_code/") && relativePath.endsWith(".py"),
18033
+ matches: (relativePath)=>relativePath.startsWith("server_code/") && relativePath.endsWith(".py") && !isRootCodePackageMarkerPath(relativePath),
17958
18034
  entityType: "server_modules",
17959
18035
  extractName: extractPythonName,
17960
18036
  savePathPrefix: [
@@ -23248,14 +23324,20 @@ print(json.dumps({"issues": issues}))
23248
23324
  if (result.ok) return {
23249
23325
  file,
23250
23326
  type: result.target,
23251
- valid: true
23327
+ valid: true,
23328
+ ...result.warnings && result.warnings.length > 0 ? {
23329
+ warnings: result.warnings
23330
+ } : {}
23252
23331
  };
23253
23332
  return {
23254
23333
  file,
23255
23334
  type: result.target,
23256
23335
  valid: false,
23257
23336
  error: result.message,
23258
- issues: result.issues
23337
+ issues: result.issues,
23338
+ ...result.warnings && result.warnings.length > 0 ? {
23339
+ warnings: result.warnings
23340
+ } : {}
23259
23341
  };
23260
23342
  }
23261
23343
  function logValidationFailure(fileResult) {
@@ -23265,6 +23347,14 @@ print(json.dumps({"issues": issues}))
23265
23347
  logger_logger.error(` - ${issuePath}: ${issue.message}`);
23266
23348
  }
23267
23349
  }
23350
+ function formatValidationWarning(file, warning) {
23351
+ const warningPath = warning.path.length > 0 ? warning.path : "root";
23352
+ const location = void 0 !== warning.line && void 0 !== warning.column ? `${file}:${warning.line}:${warning.column}` : file;
23353
+ return `${location}: ${warningPath}: ${warning.message}`;
23354
+ }
23355
+ function logValidationWarnings(fileResult) {
23356
+ for (const warning of fileResult.warnings ?? [])logger_logger.warn(formatValidationWarning(fileResult.file, warning));
23357
+ }
23268
23358
  function handleValidateFile(file) {
23269
23359
  const fileResult = validateSingleFile(file);
23270
23360
  if (fileResult.valid) {
@@ -23272,10 +23362,16 @@ print(json.dumps({"issues": issues}))
23272
23362
  data: {
23273
23363
  file: fileResult.file,
23274
23364
  type: fileResult.type,
23275
- valid: true
23365
+ valid: true,
23366
+ ...fileResult.warnings && fileResult.warnings.length > 0 ? {
23367
+ warnings: fileResult.warnings
23368
+ } : {}
23276
23369
  }
23277
23370
  });
23278
- else logger_logger.success(`${fileResult.file} is valid (${fileResult.type})`);
23371
+ else {
23372
+ logger_logger.success(`${fileResult.file} is valid (${fileResult.type})`);
23373
+ logValidationWarnings(fileResult);
23374
+ }
23279
23375
  return;
23280
23376
  }
23281
23377
  if (getGlobalOutputConfig().jsonMode) logJsonResult(false, {
@@ -23283,10 +23379,16 @@ print(json.dumps({"issues": issues}))
23283
23379
  data: {
23284
23380
  file: fileResult.file,
23285
23381
  type: fileResult.type,
23286
- issues: fileResult.issues ?? []
23382
+ issues: fileResult.issues ?? [],
23383
+ ...fileResult.warnings && fileResult.warnings.length > 0 ? {
23384
+ warnings: fileResult.warnings
23385
+ } : {}
23287
23386
  }
23288
23387
  });
23289
- else logValidationFailure(fileResult);
23388
+ else {
23389
+ logValidationFailure(fileResult);
23390
+ logValidationWarnings(fileResult);
23391
+ }
23290
23392
  process.exitCode = 1;
23291
23393
  }
23292
23394
  function handleValidateDirectory(dir) {
@@ -23316,8 +23418,13 @@ print(json.dumps({"issues": issues}))
23316
23418
  files: fileResults
23317
23419
  }
23318
23420
  });
23319
- else for (const fileResult of fileResults)if (fileResult.valid) logger_logger.success(`${fileResult.file} is valid (${fileResult.type})`);
23320
- else logValidationFailure(fileResult);
23421
+ else for (const fileResult of fileResults)if (fileResult.valid) {
23422
+ logger_logger.success(`${fileResult.file} is valid (${fileResult.type})`);
23423
+ logValidationWarnings(fileResult);
23424
+ } else {
23425
+ logValidationFailure(fileResult);
23426
+ logValidationWarnings(fileResult);
23427
+ }
23321
23428
  if (failedResults.length > 0) process.exitCode = 1;
23322
23429
  }
23323
23430
  function getUpdateInstructions(platform) {
package/dist/index.js CHANGED
@@ -16285,15 +16285,73 @@ Promise.resolve(executeGitCredentialOperation(process.argv[2] || "get", {
16285
16285
  message
16286
16286
  });
16287
16287
  }
16288
+ function offsetToLocation(source, offset) {
16289
+ const safeOffset = Math.max(0, Math.min(offset, source.length));
16290
+ let line = 1;
16291
+ let column = 1;
16292
+ for(let index = 0; index < safeOffset; index += 1){
16293
+ const char = source[index];
16294
+ if ("\n" === char) {
16295
+ line += 1;
16296
+ column = 1;
16297
+ } else column += 1;
16298
+ }
16299
+ return {
16300
+ line,
16301
+ column,
16302
+ offset: safeOffset
16303
+ };
16304
+ }
16305
+ function warningLocationFields(source, bodyStartOffset, warning) {
16306
+ if ("number" != typeof warning.from) return {};
16307
+ const start = offsetToLocation(source, bodyStartOffset + warning.from);
16308
+ const fields = {
16309
+ line: start.line,
16310
+ column: start.column,
16311
+ offset: start.offset
16312
+ };
16313
+ if ("number" == typeof warning.to) {
16314
+ const end = offsetToLocation(source, bodyStartOffset + warning.to);
16315
+ fields.endLine = end.line;
16316
+ fields.endColumn = end.column;
16317
+ fields.endOffset = end.offset;
16318
+ }
16319
+ return fields;
16320
+ }
16321
+ function parserWarnings(parsed, source, bodyStartOffset) {
16322
+ const warnings = parsed.warnings ?? [];
16323
+ return warnings.map((warning)=>({
16324
+ path: warning.path,
16325
+ message: warning.message,
16326
+ ...warning.code ? {
16327
+ code: warning.code
16328
+ } : {},
16329
+ ...warning.name ? {
16330
+ name: warning.name
16331
+ } : {},
16332
+ ...warning.attrName ? {
16333
+ attrName: warning.attrName
16334
+ } : {},
16335
+ ...warning.tagName ? {
16336
+ tagName: warning.tagName
16337
+ } : {},
16338
+ ...warning.eventName ? {
16339
+ eventName: warning.eventName
16340
+ } : {},
16341
+ ...warningLocationFields(source, bodyStartOffset, warning)
16342
+ }));
16343
+ }
16288
16344
  function splitHtmlFormTemplateFrontmatter(htmlContent) {
16289
16345
  const match = htmlContent.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
16290
16346
  if (!match) return {
16291
16347
  frontmatter: null,
16292
- body: htmlContent
16348
+ body: htmlContent,
16349
+ bodyStartOffset: 0
16293
16350
  };
16294
16351
  return {
16295
16352
  frontmatter: match[1],
16296
- body: htmlContent.slice(match[0].length)
16353
+ body: htmlContent.slice(match[0].length),
16354
+ bodyStartOffset: match[0].length
16297
16355
  };
16298
16356
  }
16299
16357
  function validateHtmlFrontmatter(frontmatterYaml) {
@@ -16324,8 +16382,8 @@ Promise.resolve(executeGitCredentialOperation(process.argv[2] || "get", {
16324
16382
  function validateParsedHtmlTemplate(parsed) {
16325
16383
  return validateFormTemplateData(parsed);
16326
16384
  }
16327
- function validateFormTemplateHtml(htmlContent) {
16328
- const { frontmatter, body } = splitHtmlFormTemplateFrontmatter(htmlContent);
16385
+ function validateFormTemplateHtml(htmlContent, parseHtml = form_template_parser_namespaceObject.parseSerializedHtml) {
16386
+ const { frontmatter, body, bodyStartOffset } = splitHtmlFormTemplateFrontmatter(htmlContent);
16329
16387
  if (null !== frontmatter) {
16330
16388
  const frontmatterIssues = validateHtmlFrontmatter(frontmatter);
16331
16389
  if (frontmatterIssues.length > 0) return {
@@ -16336,7 +16394,9 @@ Promise.resolve(executeGitCredentialOperation(process.argv[2] || "get", {
16336
16394
  }
16337
16395
  let parsed;
16338
16396
  try {
16339
- parsed = (0, form_template_parser_namespaceObject.parseSerializedHtml)(body);
16397
+ parsed = parseHtml(body, {
16398
+ warnings: true
16399
+ });
16340
16400
  } catch (error) {
16341
16401
  return {
16342
16402
  ok: false,
@@ -16349,13 +16409,20 @@ Promise.resolve(executeGitCredentialOperation(process.argv[2] || "get", {
16349
16409
  ]
16350
16410
  };
16351
16411
  }
16412
+ const warnings = parserWarnings(parsed, htmlContent, bodyStartOffset);
16352
16413
  const issues = validateParsedHtmlTemplate(parsed);
16353
16414
  if (issues.length > 0) return {
16354
16415
  ok: false,
16355
16416
  message: "form_template.html is invalid for Anvil",
16356
- issues
16357
- };
16358
- return {
16417
+ issues,
16418
+ ...warnings.length > 0 ? {
16419
+ warnings
16420
+ } : {}
16421
+ };
16422
+ return warnings.length > 0 ? {
16423
+ ok: true,
16424
+ warnings
16425
+ } : {
16359
16426
  ok: true
16360
16427
  };
16361
16428
  }
@@ -16625,6 +16692,16 @@ print(json.dumps({"issues": issues}))
16625
16692
  message
16626
16693
  });
16627
16694
  }
16695
+ function validPathResult(target, warnings) {
16696
+ return warnings && warnings.length > 0 ? {
16697
+ ok: true,
16698
+ target,
16699
+ warnings
16700
+ } : {
16701
+ ok: true,
16702
+ target
16703
+ };
16704
+ }
16628
16705
  function formatValidationPath(path) {
16629
16706
  return path || "root";
16630
16707
  }
@@ -16802,6 +16879,9 @@ print(json.dumps({"issues": issues}))
16802
16879
  if (void 0 === services || !Array.isArray(services)) return issues;
16803
16880
  services.forEach((service, index)=>{
16804
16881
  if (!validators_isPlainObject(service) || "/runtime/services/anvil/users.yml" !== service.source) return;
16882
+ if (validators_isPlainObject(service.server_config) && void 0 !== service.server_config.user_table) {
16883
+ if ("string" != typeof service.server_config.user_table && "number" != typeof service.server_config.user_table) validators_pushIssue(issues, `${path}[${index}].server_config.user_table`, "must be a table Python name string or legacy table id number");
16884
+ } else validators_pushIssue(issues, `${path}[${index}].server_config.user_table`, 'is required for the Users service; this is usually "users"');
16805
16885
  if (!validators_isPlainObject(service.client_config)) return;
16806
16886
  if (true === service.client_config.allow_remember_me && void 0 === service.client_config.remember_me_days) validators_pushIssue(issues, `${path}[${index}].client_config.remember_me_days`, "must be set if allow_remember_me is true");
16807
16887
  });
@@ -16993,10 +17073,7 @@ print(json.dumps({"issues": issues}))
16993
17073
  ]
16994
17074
  };
16995
17075
  const result = validateAnvilYaml(fileContent);
16996
- return result.ok ? {
16997
- ok: true,
16998
- target
16999
- } : {
17076
+ return result.ok ? validPathResult(target, result.warnings) : {
17000
17077
  ...result,
17001
17078
  target
17002
17079
  };
@@ -17019,10 +17096,7 @@ print(json.dumps({"issues": issues}))
17019
17096
  };
17020
17097
  }
17021
17098
  const result = validateFormTemplate(fileContent);
17022
- return result.ok ? {
17023
- ok: true,
17024
- target
17025
- } : {
17099
+ return result.ok ? validPathResult(target, result.warnings) : {
17026
17100
  ...result,
17027
17101
  target
17028
17102
  };
@@ -17045,10 +17119,7 @@ print(json.dumps({"issues": issues}))
17045
17119
  };
17046
17120
  }
17047
17121
  const result = validateFormTemplateHtml(fileContent);
17048
- return result.ok ? {
17049
- ok: true,
17050
- target
17051
- } : {
17122
+ return result.ok ? validPathResult(target, result.warnings) : {
17052
17123
  ...result,
17053
17124
  target
17054
17125
  };
@@ -17074,10 +17145,7 @@ print(json.dumps({"issues": issues}))
17074
17145
  };
17075
17146
  }
17076
17147
  const result = validatePython(filePath, fileContent, appRoot);
17077
- return result.ok ? {
17078
- ok: true,
17079
- target
17080
- } : {
17148
+ return result.ok ? validPathResult(target, result.warnings) : {
17081
17149
  ...result,
17082
17150
  target
17083
17151
  };
@@ -17097,6 +17165,10 @@ print(json.dumps({"issues": issues}))
17097
17165
  function normalizeClientCodePath(relativePath) {
17098
17166
  return relativePath.replace(/\\/g, "/");
17099
17167
  }
17168
+ function isRootCodePackageMarkerPath(relativePath) {
17169
+ const normalized = relativePath.replace(/\\/g, "/");
17170
+ return "client_code/__init__.py" === normalized || "server_code/__init__.py" === normalized;
17171
+ }
17100
17172
  function isServerRequirementsPath(relativePath) {
17101
17173
  return "server_code/requirements.txt" === relativePath.replace(/\\/g, "/");
17102
17174
  }
@@ -17192,8 +17264,12 @@ print(json.dumps({"issues": issues}))
17192
17264
  const parts = relativePath.split("/");
17193
17265
  if (2 === parts.length) return "scripts";
17194
17266
  }
17195
- if (relativePath.startsWith("server_code/") && relativePath.endsWith(".py")) return "server_modules";
17267
+ if (relativePath.startsWith("server_code/") && relativePath.endsWith(".py")) {
17268
+ if (isRootCodePackageMarkerPath(relativePath)) return null;
17269
+ return "server_modules";
17270
+ }
17196
17271
  if (relativePath.startsWith("client_code/") && relativePath.endsWith(".py")) {
17272
+ if (isRootCodePackageMarkerPath(relativePath)) return null;
17197
17273
  const isPackageInit = relativePath.endsWith("__init__.py");
17198
17274
  const kind = isPackageInit ? "package" : "module";
17199
17275
  const className = extractPythonName(relativePath);
@@ -17408,11 +17484,11 @@ print(json.dumps({"issues": issues}))
17408
17484
  handle: handleScriptsChange
17409
17485
  },
17410
17486
  {
17411
- matches: (relativePath)=>relativePath.startsWith("server_code/") && relativePath.endsWith(".py"),
17487
+ matches: (relativePath)=>relativePath.startsWith("server_code/") && relativePath.endsWith(".py") && !isRootCodePackageMarkerPath(relativePath),
17412
17488
  handle: handleServerCodeChange
17413
17489
  },
17414
17490
  {
17415
- matches: (relativePath)=>relativePath.startsWith("client_code/") && relativePath.endsWith(".py"),
17491
+ matches: (relativePath)=>relativePath.startsWith("client_code/") && relativePath.endsWith(".py") && !isRootCodePackageMarkerPath(relativePath),
17416
17492
  handle: handleClientCodeChange
17417
17493
  },
17418
17494
  {
@@ -17948,7 +18024,7 @@ print(json.dumps({"issues": issues}))
17948
18024
  const DELETION_ROUTES = [
17949
18025
  {
17950
18026
  matches: (relativePath, editorYaml)=>{
17951
- if (!relativePath.startsWith("client_code/") || !relativePath.endsWith(".py")) return false;
18027
+ if (!relativePath.startsWith("client_code/") || !relativePath.endsWith(".py") || isRootCodePackageMarkerPath(relativePath)) return false;
17952
18028
  const className = extractPythonName(relativePath);
17953
18029
  return editorYaml.hasId("forms", className);
17954
18030
  },
@@ -17960,7 +18036,7 @@ print(json.dumps({"issues": issues}))
17960
18036
  },
17961
18037
  {
17962
18038
  matches: (relativePath, editorYaml)=>{
17963
- if (!relativePath.startsWith("client_code/") || !relativePath.endsWith(".py")) return false;
18039
+ if (!relativePath.startsWith("client_code/") || !relativePath.endsWith(".py") || isRootCodePackageMarkerPath(relativePath)) return false;
17964
18040
  const className = extractPythonName(relativePath);
17965
18041
  return !editorYaml.hasId("forms", className);
17966
18042
  },
@@ -17983,7 +18059,7 @@ print(json.dumps({"issues": issues}))
17983
18059
  ]
17984
18060
  },
17985
18061
  {
17986
- matches: (relativePath)=>relativePath.startsWith("server_code/") && relativePath.endsWith(".py"),
18062
+ matches: (relativePath)=>relativePath.startsWith("server_code/") && relativePath.endsWith(".py") && !isRootCodePackageMarkerPath(relativePath),
17987
18063
  entityType: "server_modules",
17988
18064
  extractName: extractPythonName,
17989
18065
  savePathPrefix: [
package/dist/program.d.ts CHANGED
@@ -1,5 +1,22 @@
1
1
  import { Command } from "commander";
2
+ type ValidateCommandWarning = {
3
+ path: string;
4
+ message: string;
5
+ code?: string;
6
+ name?: string;
7
+ attrName?: string;
8
+ tagName?: string;
9
+ eventName?: string;
10
+ line?: number;
11
+ column?: number;
12
+ endLine?: number;
13
+ endColumn?: number;
14
+ offset?: number;
15
+ endOffset?: number;
16
+ };
17
+ export declare function formatValidationWarning(file: string, warning: ValidateCommandWarning): string;
2
18
  export declare function getUpdateInstructions(platform: NodeJS.Platform): string[];
3
19
  export declare function handleUpdateCommand(): Promise<void>;
4
20
  export declare function buildProgram(): Command;
21
+ export {};
5
22
  //# sourceMappingURL=program.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA2LpC,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,GAAG,MAAM,EAAE,CAezE;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAwFzD;AAiBD,wBAAgB,YAAY,IAAI,OAAO,CAkGtC"}
1
+ {"version":3,"file":"program.d.ts","sourceRoot":"","sources":["../src/program.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAuDpC,KAAK,sBAAsB,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AA2EF,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,sBAAsB,GAAG,MAAM,CAO7F;AA0FD,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,CAAC,QAAQ,GAAG,MAAM,EAAE,CAezE;AAED,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAwFzD;AAiBD,wBAAgB,YAAY,IAAI,OAAO,CAkGtC"}
@@ -1,10 +1,16 @@
1
1
  import { type ParsedHtmlTemplate } from "@anvil-works/form-template-parser";
2
2
  import type { FormTemplateValidationResult, ValidationIssue } from "./validators";
3
+ type ParseHtmlOptions = {
4
+ warnings?: boolean;
5
+ };
6
+ type ParseHtml = (html: string, options?: ParseHtmlOptions) => ParsedHtmlTemplate;
3
7
  export declare function splitHtmlFormTemplateFrontmatter(htmlContent: string): {
4
8
  frontmatter: string | null;
5
9
  body: string;
10
+ bodyStartOffset: number;
6
11
  };
7
12
  export declare function validateHtmlFrontmatter(frontmatterYaml: string): ValidationIssue[];
8
13
  export declare function validateParsedHtmlTemplate(parsed: ParsedHtmlTemplate): ValidationIssue[];
9
- export declare function validateFormTemplateHtml(htmlContent: string): FormTemplateValidationResult;
14
+ export declare function validateFormTemplateHtml(htmlContent: string, parseHtml?: ParseHtml): FormTemplateValidationResult;
15
+ export {};
10
16
  //# sourceMappingURL=validateFormTemplateHtml.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validateFormTemplateHtml.d.ts","sourceRoot":"","sources":["../src/validateFormTemplateHtml.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,KAAK,kBAAkB,EAC1B,MAAM,mCAAmC,CAAC;AAM3C,OAAO,KAAK,EAAE,4BAA4B,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAmClF,wBAAgB,gCAAgC,CAAC,WAAW,EAAE,MAAM,GAAG;IACnE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;CAChB,CASA;AAED,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,MAAM,GAAG,eAAe,EAAE,CAyClF;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,kBAAkB,GAAG,eAAe,EAAE,CAExF;AAED,wBAAgB,wBAAwB,CAAC,WAAW,EAAE,MAAM,GAAG,4BAA4B,CAyC1F"}
1
+ {"version":3,"file":"validateFormTemplateHtml.d.ts","sourceRoot":"","sources":["../src/validateFormTemplateHtml.ts"],"names":[],"mappings":"AAAA,OAAO,EAEH,KAAK,kBAAkB,EAC1B,MAAM,mCAAmC,CAAC;AAM3C,OAAO,KAAK,EAAE,4BAA4B,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAmClF,KAAK,gBAAgB,GAAG;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAC/C,KAAK,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,KAAK,kBAAkB,CAAC;AA0ElF,wBAAgB,gCAAgC,CAAC,WAAW,EAAE,MAAM,GAAG;IACnE,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,eAAe,EAAE,MAAM,CAAC;CAC3B,CAUA;AAED,wBAAgB,uBAAuB,CAAC,eAAe,EAAE,MAAM,GAAG,eAAe,EAAE,CAyClF;AAED,wBAAgB,0BAA0B,CAAC,MAAM,EAAE,kBAAkB,GAAG,eAAe,EAAE,CAExF;AAED,wBAAgB,wBAAwB,CACpC,WAAW,EAAE,MAAM,EACnB,SAAS,GAAE,SAA4C,GACxD,4BAA4B,CA2C9B"}
@@ -1,10 +1,12 @@
1
1
  import type { ValidationIssue } from "./validators";
2
2
  export type PythonValidationResult = {
3
3
  ok: true;
4
+ warnings?: ValidationIssue[];
4
5
  } | {
5
6
  ok: false;
6
7
  message: string;
7
8
  issues: ValidationIssue[];
9
+ warnings?: ValidationIssue[];
8
10
  };
9
11
  export type PythonInterpreterCommand = {
10
12
  command: string;
@@ -1 +1 @@
1
- {"version":3,"file":"validatePython.d.ts","sourceRoot":"","sources":["../src/validatePython.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,MAAM,sBAAsB,GAC5B;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IACI,EAAE,EAAE,KAAK,CAAC;IACV,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC7B,CAAC;AAER,MAAM,MAAM,wBAAwB,GAAG;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,KAAK,WAAW,GAAG,CACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE;IAAE,QAAQ,EAAE,cAAc,CAAA;CAAE,KACpC;IAAE,KAAK,CAAC,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAuE9C,wBAAgB,qBAAqB,CACjC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,KAAK,GAAE,WAAuB,GAC/B,wBAAwB,GAAG,IAAI,CAkBjC;AAiCD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,sBAAsB,CAsEpH"}
1
+ {"version":3,"file":"validatePython.d.ts","sourceRoot":"","sources":["../src/validatePython.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAEpD,MAAM,MAAM,sBAAsB,GAC5B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAA;CAAE,GAC1C;IACI,EAAE,EAAE,KAAK,CAAC;IACV,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;CAChC,CAAC;AAER,MAAM,MAAM,wBAAwB,GAAG;IACnC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,KAAK,WAAW,GAAG,CACf,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE;IAAE,QAAQ,EAAE,cAAc,CAAA;CAAE,KACpC;IAAE,KAAK,CAAC,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC;AAuE9C,wBAAgB,qBAAqB,CACjC,GAAG,GAAE,MAAM,CAAC,UAAwB,EACpC,KAAK,GAAE,WAAuB,GAC/B,wBAAwB,GAAG,IAAI,CAkBjC;AAiCD,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,GAAG,sBAAsB,CAsEpH"}
@@ -1,30 +1,47 @@
1
1
  export type ValidationIssue = {
2
2
  path: string;
3
3
  message: string;
4
+ code?: string;
5
+ name?: string;
6
+ attrName?: string;
7
+ tagName?: string;
8
+ eventName?: string;
9
+ line?: number;
10
+ column?: number;
11
+ endLine?: number;
12
+ endColumn?: number;
13
+ offset?: number;
14
+ endOffset?: number;
4
15
  };
5
16
  export type FormTemplateValidationResult = {
6
17
  ok: true;
18
+ warnings?: ValidationIssue[];
7
19
  } | {
8
20
  ok: false;
9
21
  message: string;
10
22
  issues: ValidationIssue[];
23
+ warnings?: ValidationIssue[];
11
24
  };
12
25
  export type AnvilYamlValidationResult = {
13
26
  ok: true;
27
+ warnings?: ValidationIssue[];
14
28
  } | {
15
29
  ok: false;
16
30
  message: string;
17
31
  issues: ValidationIssue[];
32
+ warnings?: ValidationIssue[];
18
33
  };
19
34
  export type ValidationTarget = "anvil.yaml" | "form_template.yaml" | "form_template.html" | "python";
20
35
  export type ValidatePathResult = {
21
36
  ok: true;
22
37
  target: ValidationTarget;
38
+ warnings?: ValidationIssue[];
23
39
  } | {
24
40
  ok: false;
25
41
  target: ValidationTarget | "unknown";
26
42
  message: string;
27
43
  issues: ValidationIssue[];
44
+ warnings?: ValidationIssue[];
28
45
  };
29
46
  export declare function formatValidationPath(path: string): string;
30
47
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,eAAe,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;CACnB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAClC;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IACI,EAAE,EAAE,KAAK,CAAC;IACV,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC7B,CAAC;AAER,MAAM,MAAM,yBAAyB,GAC/B;IAAE,EAAE,EAAE,IAAI,CAAA;CAAE,GACZ;IACI,EAAE,EAAE,KAAK,CAAC;IACV,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC7B,CAAC;AAER,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,oBAAoB,GAAG,oBAAoB,GAAG,QAAQ,CAAC;AAErG,MAAM,MAAM,kBAAkB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAA;CAAE,GACtC;IACI,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,eAAe,EAAE,CAAC;CAC7B,CAAC;AAoER,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,UAEhD;AAgBD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,4BAA4B,CA0BtF;AAuZD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,yBAAyB,CAkFhF;AAED,iBAAS,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CA4BxE;AAED,OAAO,EAAE,qBAAqB,EAAE,CAAC;AAOjC,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBhE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,kBAAkB,CAoItF"}
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":"AAYA,MAAM,MAAM,eAAe,GAAG;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,4BAA4B,GAClC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAA;CAAE,GAC1C;IACI,EAAE,EAAE,KAAK,CAAC;IACV,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;CAChC,CAAC;AAER,MAAM,MAAM,yBAAyB,GAC/B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAA;CAAE,GAC1C;IACI,EAAE,EAAE,KAAK,CAAC;IACV,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;CAChC,CAAC;AAER,MAAM,MAAM,gBAAgB,GAAG,YAAY,GAAG,oBAAoB,GAAG,oBAAoB,GAAG,QAAQ,CAAC;AAErG,MAAM,MAAM,kBAAkB,GACxB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAA;CAAE,GACpE;IACI,EAAE,EAAE,KAAK,CAAC;IACV,MAAM,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACrC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,eAAe,EAAE,CAAC;IAC1B,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;CAChC,CAAC;AAwER,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,UAEhD;AAgBD;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,GAAG,4BAA4B,CA0BtF;AAqaD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,WAAW,EAAE,MAAM,GAAG,yBAAyB,CAkFhF;AAED,iBAAS,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,gBAAgB,GAAG,IAAI,CA4BxE;AAED,OAAO,EAAE,qBAAqB,EAAE,CAAC;AAOjC,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAkBhE;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,kBAAkB,CAoItF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anvil-works/anvil-cli",
3
- "version": "0.8.0-canary.0",
3
+ "version": "0.8.0-canary.2",
4
4
  "description": "CLI tool for developing Anvil apps locally",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/api.d.ts",
@@ -64,7 +64,7 @@
64
64
  "typescript": "^5.9.3"
65
65
  },
66
66
  "dependencies": {
67
- "@anvil-works/form-template-parser": "0.0.3",
67
+ "@anvil-works/form-template-parser": "0.0.4",
68
68
  "@napi-rs/keyring": "^1.2.0",
69
69
  "@types/inquirer": "^9.0.9",
70
70
  "@types/js-yaml": "^4.0.9",