@anvil-works/anvil-cli 0.8.0-canary.1 → 0.8.0-canary.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/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, options = {}) {
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,12 @@ 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
+ ...options.formSpecPackageContext ? {
16371
+ formSpecPackageContext: options.formSpecPackageContext
16372
+ } : {}
16373
+ });
16311
16374
  } catch (error) {
16312
16375
  return {
16313
16376
  ok: false,
@@ -16320,13 +16383,20 @@ Promise.resolve(executeGitCredentialOperation(process.argv[2] || "get", {
16320
16383
  ]
16321
16384
  };
16322
16385
  }
16386
+ const warnings = parserWarnings(parsed, htmlContent, bodyStartOffset);
16323
16387
  const issues = validateParsedHtmlTemplate(parsed);
16324
16388
  if (issues.length > 0) return {
16325
16389
  ok: false,
16326
16390
  message: "form_template.html is invalid for Anvil",
16327
- issues
16328
- };
16329
- return {
16391
+ issues,
16392
+ ...warnings.length > 0 ? {
16393
+ warnings
16394
+ } : {}
16395
+ };
16396
+ return warnings.length > 0 ? {
16397
+ ok: true,
16398
+ warnings
16399
+ } : {
16330
16400
  ok: true
16331
16401
  };
16332
16402
  }
@@ -16596,6 +16666,16 @@ print(json.dumps({"issues": issues}))
16596
16666
  message
16597
16667
  });
16598
16668
  }
16669
+ function validPathResult(target, warnings) {
16670
+ return warnings && warnings.length > 0 ? {
16671
+ ok: true,
16672
+ target,
16673
+ warnings
16674
+ } : {
16675
+ ok: true,
16676
+ target
16677
+ };
16678
+ }
16599
16679
  function formatValidationPath(path) {
16600
16680
  return path || "root";
16601
16681
  }
@@ -16939,7 +17019,7 @@ print(json.dumps({"issues": issues}))
16939
17019
  currentDir = parentDir;
16940
17020
  }
16941
17021
  }
16942
- function validatePath(filePath, fileContent) {
17022
+ function validatePath(filePath, fileContent, options = {}) {
16943
17023
  const target = inferValidationTarget(filePath);
16944
17024
  const existingPath = resolveExistingPath(filePath);
16945
17025
  const appRoot = findAnvilAppRoot(filePath);
@@ -16967,10 +17047,7 @@ print(json.dumps({"issues": issues}))
16967
17047
  ]
16968
17048
  };
16969
17049
  const result = validateAnvilYaml(fileContent);
16970
- return result.ok ? {
16971
- ok: true,
16972
- target
16973
- } : {
17050
+ return result.ok ? validPathResult(target, result.warnings) : {
16974
17051
  ...result,
16975
17052
  target
16976
17053
  };
@@ -16993,10 +17070,7 @@ print(json.dumps({"issues": issues}))
16993
17070
  };
16994
17071
  }
16995
17072
  const result = validateFormTemplate(fileContent);
16996
- return result.ok ? {
16997
- ok: true,
16998
- target
16999
- } : {
17073
+ return result.ok ? validPathResult(target, result.warnings) : {
17000
17074
  ...result,
17001
17075
  target
17002
17076
  };
@@ -17018,11 +17092,10 @@ print(json.dumps({"issues": issues}))
17018
17092
  ]
17019
17093
  };
17020
17094
  }
17021
- const result = validateFormTemplateHtml(fileContent);
17022
- return result.ok ? {
17023
- ok: true,
17024
- target
17025
- } : {
17095
+ const result = validateFormTemplateHtml(fileContent, void 0, {
17096
+ formSpecPackageContext: options.formSpecPackageContext
17097
+ });
17098
+ return result.ok ? validPathResult(target, result.warnings) : {
17026
17099
  ...result,
17027
17100
  target
17028
17101
  };
@@ -17048,10 +17121,7 @@ print(json.dumps({"issues": issues}))
17048
17121
  };
17049
17122
  }
17050
17123
  const result = validatePython(filePath, fileContent, appRoot);
17051
- return result.ok ? {
17052
- ok: true,
17053
- target
17054
- } : {
17124
+ return result.ok ? validPathResult(target, result.warnings) : {
17055
17125
  ...result,
17056
17126
  target
17057
17127
  };
@@ -23237,7 +23307,7 @@ print(json.dumps({"issues": issues}))
23237
23307
  walk(dir);
23238
23308
  return files.sort();
23239
23309
  }
23240
- function validateSingleFile(file) {
23310
+ async function validateSingleFile(file) {
23241
23311
  let fileContent;
23242
23312
  try {
23243
23313
  fileContent = (0, external_fs_.readFileSync)(file, "utf8");
@@ -23255,18 +23325,27 @@ print(json.dumps({"issues": issues}))
23255
23325
  ]
23256
23326
  };
23257
23327
  }
23258
- const result = validatePath(file, fileContent);
23328
+ const formSpecPackageContext = "form_template.html" === inferValidationTarget(file) ? await buildFormSpecPackageContext(file) : void 0;
23329
+ const result = validatePath(file, fileContent, {
23330
+ formSpecPackageContext
23331
+ });
23259
23332
  if (result.ok) return {
23260
23333
  file,
23261
23334
  type: result.target,
23262
- valid: true
23335
+ valid: true,
23336
+ ...result.warnings && result.warnings.length > 0 ? {
23337
+ warnings: result.warnings
23338
+ } : {}
23263
23339
  };
23264
23340
  return {
23265
23341
  file,
23266
23342
  type: result.target,
23267
23343
  valid: false,
23268
23344
  error: result.message,
23269
- issues: result.issues
23345
+ issues: result.issues,
23346
+ ...result.warnings && result.warnings.length > 0 ? {
23347
+ warnings: result.warnings
23348
+ } : {}
23270
23349
  };
23271
23350
  }
23272
23351
  function logValidationFailure(fileResult) {
@@ -23276,17 +23355,31 @@ print(json.dumps({"issues": issues}))
23276
23355
  logger_logger.error(` - ${issuePath}: ${issue.message}`);
23277
23356
  }
23278
23357
  }
23279
- function handleValidateFile(file) {
23280
- const fileResult = validateSingleFile(file);
23358
+ function formatValidationWarning(file, warning) {
23359
+ const warningPath = warning.path.length > 0 ? warning.path : "root";
23360
+ const location = void 0 !== warning.line && void 0 !== warning.column ? `${file}:${warning.line}:${warning.column}` : file;
23361
+ return `${location}: ${warningPath}: ${warning.message}`;
23362
+ }
23363
+ function logValidationWarnings(fileResult) {
23364
+ for (const warning of fileResult.warnings ?? [])logger_logger.warn(formatValidationWarning(fileResult.file, warning));
23365
+ }
23366
+ async function handleValidateFile(file) {
23367
+ const fileResult = await validateSingleFile(file);
23281
23368
  if (fileResult.valid) {
23282
23369
  if (getGlobalOutputConfig().jsonMode) logJsonResult(true, {
23283
23370
  data: {
23284
23371
  file: fileResult.file,
23285
23372
  type: fileResult.type,
23286
- valid: true
23373
+ valid: true,
23374
+ ...fileResult.warnings && fileResult.warnings.length > 0 ? {
23375
+ warnings: fileResult.warnings
23376
+ } : {}
23287
23377
  }
23288
23378
  });
23289
- else logger_logger.success(`${fileResult.file} is valid (${fileResult.type})`);
23379
+ else {
23380
+ logger_logger.success(`${fileResult.file} is valid (${fileResult.type})`);
23381
+ logValidationWarnings(fileResult);
23382
+ }
23290
23383
  return;
23291
23384
  }
23292
23385
  if (getGlobalOutputConfig().jsonMode) logJsonResult(false, {
@@ -23294,13 +23387,19 @@ print(json.dumps({"issues": issues}))
23294
23387
  data: {
23295
23388
  file: fileResult.file,
23296
23389
  type: fileResult.type,
23297
- issues: fileResult.issues ?? []
23390
+ issues: fileResult.issues ?? [],
23391
+ ...fileResult.warnings && fileResult.warnings.length > 0 ? {
23392
+ warnings: fileResult.warnings
23393
+ } : {}
23298
23394
  }
23299
23395
  });
23300
- else logValidationFailure(fileResult);
23396
+ else {
23397
+ logValidationFailure(fileResult);
23398
+ logValidationWarnings(fileResult);
23399
+ }
23301
23400
  process.exitCode = 1;
23302
23401
  }
23303
- function handleValidateDirectory(dir) {
23402
+ async function handleValidateDirectory(dir) {
23304
23403
  const files = collectValidationFiles(dir);
23305
23404
  if (0 === files.length) {
23306
23405
  const error = `No supported files found under ${dir}`;
@@ -23316,7 +23415,7 @@ print(json.dumps({"issues": issues}))
23316
23415
  process.exitCode = 1;
23317
23416
  return;
23318
23417
  }
23319
- const fileResults = files.map(validateSingleFile);
23418
+ const fileResults = await Promise.all(files.map(validateSingleFile));
23320
23419
  const failedResults = fileResults.filter((result)=>!result.valid);
23321
23420
  if (getGlobalOutputConfig().jsonMode) logJsonResult(0 === failedResults.length, {
23322
23421
  error: failedResults.length > 0 ? "Validation failed" : void 0,
@@ -23327,8 +23426,13 @@ print(json.dumps({"issues": issues}))
23327
23426
  files: fileResults
23328
23427
  }
23329
23428
  });
23330
- else for (const fileResult of fileResults)if (fileResult.valid) logger_logger.success(`${fileResult.file} is valid (${fileResult.type})`);
23331
- else logValidationFailure(fileResult);
23429
+ else for (const fileResult of fileResults)if (fileResult.valid) {
23430
+ logger_logger.success(`${fileResult.file} is valid (${fileResult.type})`);
23431
+ logValidationWarnings(fileResult);
23432
+ } else {
23433
+ logValidationFailure(fileResult);
23434
+ logValidationWarnings(fileResult);
23435
+ }
23332
23436
  if (failedResults.length > 0) process.exitCode = 1;
23333
23437
  }
23334
23438
  function getUpdateInstructions(platform) {
@@ -23444,7 +23548,7 @@ print(json.dumps({"issues": issues}))
23444
23548
  program.command("update").description("Update anvil to the latest version").alias("u").action(async ()=>{
23445
23549
  await handleUpdateCommand();
23446
23550
  });
23447
- program.command("validate").description("Validate Anvil app files by path or directory (anvil.yaml, client_code/**/*.yaml, client_code/**/*.html, client_code/**/*.py, or server_code/**/*.py)").argument("<path>", "Path to file or directory").action((file)=>{
23551
+ program.command("validate").description("Validate Anvil app files by path or directory (anvil.yaml, client_code/**/*.yaml, client_code/**/*.html, client_code/**/*.py, or server_code/**/*.py)").argument("<path>", "Path to file or directory").action(async (file)=>{
23448
23552
  let pathStat;
23449
23553
  try {
23450
23554
  pathStat = (0, external_fs_.statSync)(file);
@@ -23453,8 +23557,8 @@ print(json.dumps({"issues": issues}))
23453
23557
  process.exitCode = 1;
23454
23558
  return;
23455
23559
  }
23456
- if (pathStat.isDirectory()) return void handleValidateDirectory(file);
23457
- handleValidateFile(file);
23560
+ if (pathStat.isDirectory()) return void await handleValidateDirectory(file);
23561
+ await handleValidateFile(file);
23458
23562
  });
23459
23563
  if (watchCommand) {
23460
23564
  const watchOptions = watchCommand.options.map((opt)=>{
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, options = {}) {
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,12 @@ 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
+ ...options.formSpecPackageContext ? {
16400
+ formSpecPackageContext: options.formSpecPackageContext
16401
+ } : {}
16402
+ });
16340
16403
  } catch (error) {
16341
16404
  return {
16342
16405
  ok: false,
@@ -16349,13 +16412,20 @@ Promise.resolve(executeGitCredentialOperation(process.argv[2] || "get", {
16349
16412
  ]
16350
16413
  };
16351
16414
  }
16415
+ const warnings = parserWarnings(parsed, htmlContent, bodyStartOffset);
16352
16416
  const issues = validateParsedHtmlTemplate(parsed);
16353
16417
  if (issues.length > 0) return {
16354
16418
  ok: false,
16355
16419
  message: "form_template.html is invalid for Anvil",
16356
- issues
16357
- };
16358
- return {
16420
+ issues,
16421
+ ...warnings.length > 0 ? {
16422
+ warnings
16423
+ } : {}
16424
+ };
16425
+ return warnings.length > 0 ? {
16426
+ ok: true,
16427
+ warnings
16428
+ } : {
16359
16429
  ok: true
16360
16430
  };
16361
16431
  }
@@ -16625,6 +16695,16 @@ print(json.dumps({"issues": issues}))
16625
16695
  message
16626
16696
  });
16627
16697
  }
16698
+ function validPathResult(target, warnings) {
16699
+ return warnings && warnings.length > 0 ? {
16700
+ ok: true,
16701
+ target,
16702
+ warnings
16703
+ } : {
16704
+ ok: true,
16705
+ target
16706
+ };
16707
+ }
16628
16708
  function formatValidationPath(path) {
16629
16709
  return path || "root";
16630
16710
  }
@@ -16968,7 +17048,7 @@ print(json.dumps({"issues": issues}))
16968
17048
  currentDir = parentDir;
16969
17049
  }
16970
17050
  }
16971
- function validatePath(filePath, fileContent) {
17051
+ function validatePath(filePath, fileContent, options = {}) {
16972
17052
  const target = inferValidationTarget(filePath);
16973
17053
  const existingPath = resolveExistingPath(filePath);
16974
17054
  const appRoot = findAnvilAppRoot(filePath);
@@ -16996,10 +17076,7 @@ print(json.dumps({"issues": issues}))
16996
17076
  ]
16997
17077
  };
16998
17078
  const result = validateAnvilYaml(fileContent);
16999
- return result.ok ? {
17000
- ok: true,
17001
- target
17002
- } : {
17079
+ return result.ok ? validPathResult(target, result.warnings) : {
17003
17080
  ...result,
17004
17081
  target
17005
17082
  };
@@ -17022,10 +17099,7 @@ print(json.dumps({"issues": issues}))
17022
17099
  };
17023
17100
  }
17024
17101
  const result = validateFormTemplate(fileContent);
17025
- return result.ok ? {
17026
- ok: true,
17027
- target
17028
- } : {
17102
+ return result.ok ? validPathResult(target, result.warnings) : {
17029
17103
  ...result,
17030
17104
  target
17031
17105
  };
@@ -17047,11 +17121,10 @@ print(json.dumps({"issues": issues}))
17047
17121
  ]
17048
17122
  };
17049
17123
  }
17050
- const result = validateFormTemplateHtml(fileContent);
17051
- return result.ok ? {
17052
- ok: true,
17053
- target
17054
- } : {
17124
+ const result = validateFormTemplateHtml(fileContent, void 0, {
17125
+ formSpecPackageContext: options.formSpecPackageContext
17126
+ });
17127
+ return result.ok ? validPathResult(target, result.warnings) : {
17055
17128
  ...result,
17056
17129
  target
17057
17130
  };
@@ -17077,10 +17150,7 @@ print(json.dumps({"issues": issues}))
17077
17150
  };
17078
17151
  }
17079
17152
  const result = validatePython(filePath, fileContent, appRoot);
17080
- return result.ok ? {
17081
- ok: true,
17082
- target
17083
- } : {
17153
+ return result.ok ? validPathResult(target, result.warnings) : {
17084
17154
  ...result,
17085
17155
  target
17086
17156
  };
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;AAwDpC,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;AA6EF,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,20 @@
1
- import { type ParsedHtmlTemplate } from "@anvil-works/form-template-parser";
1
+ import { type FormSpecPackageContext, type ParsedHtmlTemplate } from "@anvil-works/form-template-parser";
2
2
  import type { FormTemplateValidationResult, ValidationIssue } from "./validators";
3
+ type ParseHtmlOptions = {
4
+ warnings?: boolean;
5
+ formSpecPackageContext?: FormSpecPackageContext;
6
+ };
7
+ type ParseHtml = (html: string, options?: ParseHtmlOptions) => ParsedHtmlTemplate;
8
+ export type ValidateFormTemplateHtmlOptions = {
9
+ formSpecPackageContext?: FormSpecPackageContext;
10
+ };
3
11
  export declare function splitHtmlFormTemplateFrontmatter(htmlContent: string): {
4
12
  frontmatter: string | null;
5
13
  body: string;
14
+ bodyStartOffset: number;
6
15
  };
7
16
  export declare function validateHtmlFrontmatter(frontmatterYaml: string): ValidationIssue[];
8
17
  export declare function validateParsedHtmlTemplate(parsed: ParsedHtmlTemplate): ValidationIssue[];
9
- export declare function validateFormTemplateHtml(htmlContent: string): FormTemplateValidationResult;
18
+ export declare function validateFormTemplateHtml(htmlContent: string, parseHtml?: ParseHtml, options?: ValidateFormTemplateHtmlOptions): FormTemplateValidationResult;
19
+ export {};
10
20
  //# 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,sBAAsB,EAC3B,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,CAAC;IAAC,sBAAsB,CAAC,EAAE,sBAAsB,CAAA;CAAE,CAAC;AAChG,KAAK,SAAS,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,KAAK,kBAAkB,CAAC;AAClF,MAAM,MAAM,+BAA+B,GAAG;IAC1C,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;CACnD,CAAC;AA0EF,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,EACvD,OAAO,GAAE,+BAAoC,GAC9C,4BAA4B,CA8C9B"}
@@ -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,51 @@
1
+ import type { FormSpecPackageContext } from "@anvil-works/form-template-parser";
1
2
  export type ValidationIssue = {
2
3
  path: string;
3
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;
4
16
  };
5
17
  export type FormTemplateValidationResult = {
6
18
  ok: true;
19
+ warnings?: ValidationIssue[];
7
20
  } | {
8
21
  ok: false;
9
22
  message: string;
10
23
  issues: ValidationIssue[];
24
+ warnings?: ValidationIssue[];
11
25
  };
12
26
  export type AnvilYamlValidationResult = {
13
27
  ok: true;
28
+ warnings?: ValidationIssue[];
14
29
  } | {
15
30
  ok: false;
16
31
  message: string;
17
32
  issues: ValidationIssue[];
33
+ warnings?: ValidationIssue[];
18
34
  };
19
35
  export type ValidationTarget = "anvil.yaml" | "form_template.yaml" | "form_template.html" | "python";
20
36
  export type ValidatePathResult = {
21
37
  ok: true;
22
38
  target: ValidationTarget;
39
+ warnings?: ValidationIssue[];
23
40
  } | {
24
41
  ok: false;
25
42
  target: ValidationTarget | "unknown";
26
43
  message: string;
27
44
  issues: ValidationIssue[];
45
+ warnings?: ValidationIssue[];
46
+ };
47
+ export type ValidatePathOptions = {
48
+ formSpecPackageContext?: FormSpecPackageContext;
28
49
  };
29
50
  export declare function formatValidationPath(path: string): string;
30
51
  /**
@@ -45,5 +66,5 @@ export declare function findAnvilAppRoot(filePath: string): string | null;
45
66
  * - any form HTML under `client_code/` with a `.html` suffix
46
67
  * - any Python file under `client_code/` or `server_code/`
47
68
  */
48
- export declare function validatePath(filePath: string, fileContent: string): ValidatePathResult;
69
+ export declare function validatePath(filePath: string, fileContent: string, options?: ValidatePathOptions): ValidatePathResult;
49
70
  //# sourceMappingURL=validators.d.ts.map
@@ -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;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"}
1
+ {"version":3,"file":"validators.d.ts","sourceRoot":"","sources":["../src/validators.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,mCAAmC,CAAC;AAMhF,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;AAER,MAAM,MAAM,mBAAmB,GAAG;IAC9B,sBAAsB,CAAC,EAAE,sBAAsB,CAAC;CACnD,CAAC;AAwEF,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,CACxB,QAAQ,EAAE,MAAM,EAChB,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,mBAAwB,GAClC,kBAAkB,CAsIpB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@anvil-works/anvil-cli",
3
- "version": "0.8.0-canary.1",
3
+ "version": "0.8.0-canary.3",
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.5",
68
68
  "@napi-rs/keyring": "^1.2.0",
69
69
  "@types/inquirer": "^9.0.9",
70
70
  "@types/js-yaml": "^4.0.9",