@altopelago/aeon-cli 0.9.0 → 0.9.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.
package/dist/main.js CHANGED
@@ -225,7 +225,7 @@ Examples:
225
225
  * Exit code: 0 = valid, 1 = errors
226
226
  */
227
227
  function check(args) {
228
- const file = findFile(args);
228
+ const file = findFileWithValueFlags(args, ['--datatype-policy', '--max-input-bytes']);
229
229
  if (!file) {
230
230
  console.error('Error: No file specified');
231
231
  console.error('Usage: aeon check <file>');
@@ -242,8 +242,7 @@ function check(args) {
242
242
  console.error('Error: Invalid value for --max-input-bytes (expected a non-negative integer)');
243
243
  process.exit(2);
244
244
  }
245
- const input = readFile(file);
246
- enforceInputByteLimitOrExit(input, maxInputBytes);
245
+ const input = readFileWithLimit(file, maxInputBytes);
247
246
  const result = compile(input, {
248
247
  ...(datatypePolicy ? { datatypePolicy } : {}),
249
248
  ...(maxInputBytes !== undefined ? { maxInputBytes } : {}),
@@ -289,7 +288,7 @@ function getDefaultContractRegistryPath() {
289
288
  const specsRoot = process.env.AEONITE_SPECS_ROOT
290
289
  ? path.resolve(process.env.AEONITE_SPECS_ROOT)
291
290
  : path.resolve(repoRoot, '..', '..', 'aeonite-org', 'aeonite-specs');
292
- return path.resolve(specsRoot, 'aeon/v1/drafts/contracts/registry.json');
291
+ return path.resolve(specsRoot, 'contracts/v1/drafts/artifacts/registry.json');
293
292
  }
294
293
  /**
295
294
  * aeon fmt [file] [--write]
@@ -297,7 +296,7 @@ function getDefaultContractRegistryPath() {
297
296
  */
298
297
  function fmt(args) {
299
298
  const writeOutput = args.includes('--write');
300
- const file = findFile(args);
299
+ const file = findFileWithValueFlags(args, ['--max-input-bytes']);
301
300
  const maxInputBytes = resolveMaxInputBytes(args);
302
301
  if (writeOutput && !file) {
303
302
  console.error('Error: --write requires a file path');
@@ -308,8 +307,7 @@ function fmt(args) {
308
307
  console.error('Error: Invalid value for --max-input-bytes (expected a non-negative integer)');
309
308
  process.exit(2);
310
309
  }
311
- const input = file ? readFile(file) : readStdin();
312
- enforceInputByteLimitOrExit(input, maxInputBytes);
310
+ const input = file ? readFileWithLimit(file, maxInputBytes) : readStdin(maxInputBytes);
313
311
  const result = canonicalize(input);
314
312
  if (result.errors.length > 0) {
315
313
  for (const error of result.errors) {
@@ -331,8 +329,8 @@ function fmt(args) {
331
329
  * Purpose: human inspection (default) or JSON output
332
330
  */
333
331
  function inspect(args) {
334
- const inspectUsage = 'Usage: aeon inspect <file> [--json] [--recovery] [--annotations] [--annotations-only] [--sort-annotations] [--datatype-policy <reserved_only|allow_custom>] [--max-input-bytes <n>] [--max-attribute-depth <n>] [--max-separator-depth <n>] [--max-generic-depth <n>] [--max-nesting-depth <n>]';
335
- const file = findFileWithValueFlags(args, ['--datatype-policy', '--max-input-bytes', '--max-attribute-depth', '--max-separator-depth', '--max-generic-depth', '--max-nesting-depth']);
332
+ const inspectUsage = 'Usage: aeon inspect <file> [--json] [--recovery] [--annotations] [--annotations-only] [--sort-annotations] [--datatype-policy <reserved_only|allow_custom>] [--max-input-bytes <n>] [--max-events <n>] [--max-attribute-depth <n>] [--max-separator-depth <n>] [--max-generic-depth <n>] [--max-nesting-depth <n>]';
333
+ const file = findFileWithValueFlags(args, ['--datatype-policy', '--max-input-bytes', '--max-events', '--max-attribute-depth', '--max-separator-depth', '--max-generic-depth', '--max-nesting-depth']);
336
334
  const jsonOutput = args.includes('--json');
337
335
  const recovery = args.includes('--recovery');
338
336
  const annotationsOnly = args.includes('--annotations-only');
@@ -340,6 +338,7 @@ function inspect(args) {
340
338
  const sortAnnotations = args.includes('--sort-annotations');
341
339
  const datatypePolicy = resolveDatatypePolicy(args);
342
340
  const maxInputBytes = resolveMaxInputBytes(args);
341
+ const maxEvents = resolveDepthOption(args, '--max-events');
343
342
  const maxAttributeDepth = resolveDepthOption(args, '--max-attribute-depth');
344
343
  const maxSeparatorDepth = resolveDepthOption(args, '--max-separator-depth');
345
344
  const maxGenericDepth = resolveDepthOption(args, '--max-generic-depth');
@@ -358,6 +357,10 @@ function inspect(args) {
358
357
  console.error('Error: Invalid value for --max-input-bytes (expected a non-negative integer)');
359
358
  process.exit(2);
360
359
  }
360
+ if (maxEvents === null) {
361
+ console.error('Error: Invalid value for --max-events (expected a non-negative integer)');
362
+ process.exit(2);
363
+ }
361
364
  if (maxAttributeDepth === null) {
362
365
  console.error('Error: Invalid value for --max-attribute-depth (expected a non-negative integer)');
363
366
  process.exit(2);
@@ -374,13 +377,13 @@ function inspect(args) {
374
377
  console.error('Error: Invalid value for --max-nesting-depth (expected a non-negative integer)');
375
378
  process.exit(2);
376
379
  }
377
- const input = readFile(file);
378
- enforceInputByteLimitOrExit(input, maxInputBytes);
380
+ const input = readFileWithLimit(file, maxInputBytes);
379
381
  const result = compile(input, {
380
382
  recovery,
381
383
  emitAnnotations: includeAnnotations || annotationsOnly,
382
384
  ...(datatypePolicy ? { datatypePolicy } : {}),
383
385
  ...(maxInputBytes !== undefined ? { maxInputBytes } : {}),
386
+ ...(maxEvents !== undefined ? { maxEvents } : {}),
384
387
  ...(maxAttributeDepth !== undefined ? { maxAttributeDepth } : {}),
385
388
  ...(maxSeparatorDepth !== undefined ? { maxSeparatorDepth } : {}),
386
389
  ...(maxGenericDepth !== undefined ? { maxGenericDepth } : {}),
@@ -467,8 +470,7 @@ function finalize(args) {
467
470
  console.error(finalizeUsage);
468
471
  process.exit(2);
469
472
  }
470
- const input = readFile(file);
471
- enforceInputByteLimitOrExit(input, maxInputBytes);
473
+ const input = readFileWithLimit(file, maxInputBytes);
472
474
  const result = compile(input, {
473
475
  recovery,
474
476
  ...(datatypePolicy ? { datatypePolicy } : {}),
@@ -502,7 +504,7 @@ function bind(args) {
502
504
  console.error('Usage: aeon bind <file> [--schema <schema.json>] [--profile <id>] [--contract-registry <registry.json>] [--trailing-separator-delimiter-policy <off|warn|error>] [--datatype-policy <reserved_only|allow_custom>] [--strict|--loose] [--projected] [--include-path <$.path>] [--annotations] [--sort-annotations]');
503
505
  process.exit(2);
504
506
  }
505
- const file = findFileWithValueFlags(args, ['--schema', '--profile', '--contract-registry', '--trailing-separator-delimiter-policy', '--datatype-policy', '--include-path']);
507
+ const file = findFileWithValueFlags(args, ['--schema', '--profile', '--contract-registry', '--trailing-separator-delimiter-policy', '--datatype-policy', '--include-path', '--scope', '--max-input-bytes']);
506
508
  if (!file) {
507
509
  console.error('Error: No file specified');
508
510
  console.error('Usage: aeon bind <file> [--schema <schema.json>] [--profile <id>] [--contract-registry <registry.json>] [--trailing-separator-delimiter-policy <off|warn|error>] [--datatype-policy <reserved_only|allow_custom>] [--strict|--loose] [--projected] [--include-path <$.path>] [--annotations] [--sort-annotations]');
@@ -572,8 +574,7 @@ function bind(args) {
572
574
  console.error('Usage: aeon bind <file> [--schema <schema.json>] [--profile <id>] [--contract-registry <registry.json>] [--trailing-separator-delimiter-policy <off|warn|error>] [--datatype-policy <reserved_only|allow_custom>] [--strict|--loose] [--projected] [--include-path <$.path>] [--annotations] [--sort-annotations]');
573
575
  process.exit(2);
574
576
  }
575
- const input = readFile(file);
576
- enforceInputByteLimitOrExit(input, maxInputBytes);
577
+ const input = readFileWithLimit(file, maxInputBytes);
577
578
  const headerInfo = extractHeaderInfo(input);
578
579
  const resolvedRegistryPath = contractRegistryPath
579
580
  ? path.resolve(process.cwd(), contractRegistryPath)
@@ -685,14 +686,13 @@ function integrityValidate(args) {
685
686
  console.error('Error: Invalid value for --max-input-bytes (expected a non-negative integer)');
686
687
  process.exit(2);
687
688
  }
688
- const file = findFileWithValueFlags(args, ['--public-key', '--pubkey', '--receipt']);
689
+ const file = findFileWithValueFlags(args, ['--public-key', '--pubkey', '--receipt', '--max-input-bytes']);
689
690
  if (!file) {
690
691
  console.error('Error: No file specified');
691
692
  console.error('Usage: aeon integrity validate <file> [--strict|--loose]');
692
693
  process.exit(2);
693
694
  }
694
- const input = readFile(file);
695
- enforceInputByteLimitOrExit(input, maxInputBytes);
695
+ const input = readFileWithLimit(file, maxInputBytes);
696
696
  const compileResult = compile(input, {
697
697
  ...(maxInputBytes !== undefined ? { maxInputBytes } : {}),
698
698
  });
@@ -740,14 +740,13 @@ function integrityVerify(args) {
740
740
  console.error('Error: Invalid value for --max-input-bytes (expected a non-negative integer)');
741
741
  process.exit(2);
742
742
  }
743
- const file = findFileWithValueFlags(args, ['--public-key', '--pubkey']);
743
+ const file = findFileWithValueFlags(args, ['--public-key', '--pubkey', '--receipt', '--max-input-bytes']);
744
744
  if (!file) {
745
745
  console.error('Error: No file specified');
746
746
  console.error('Usage: aeon integrity verify <file> [--strict|--loose] [--public-key <path>] [--receipt <path>]');
747
747
  process.exit(2);
748
748
  }
749
- const input = readFile(file);
750
- enforceInputByteLimitOrExit(input, maxInputBytes);
749
+ const input = readFileWithLimit(file, maxInputBytes);
751
750
  const baseInput = removeEnvelope(input);
752
751
  const compileResult = compile(input, {
753
752
  ...(maxInputBytes !== undefined ? { maxInputBytes } : {}),
@@ -1017,7 +1016,7 @@ function integrityVerify(args) {
1017
1016
  }
1018
1017
  }
1019
1018
  function integritySign(args) {
1020
- const file = findFileWithValueFlags(args, ['--private-key', '--privkey', '--receipt']);
1019
+ const file = findFileWithValueFlags(args, ['--private-key', '--privkey', '--receipt', '--max-input-bytes']);
1021
1020
  const jsonOutput = args.includes('--json');
1022
1021
  const writeOutput = args.includes('--write');
1023
1022
  const replaceOutput = args.includes('--replace');
@@ -1039,8 +1038,7 @@ function integritySign(args) {
1039
1038
  console.error('Usage: aeon integrity sign <file> --private-key <path> [--receipt <path>]');
1040
1039
  process.exit(2);
1041
1040
  }
1042
- const input = readFile(file);
1043
- enforceInputByteLimitOrExit(input, maxInputBytes);
1041
+ const input = readFileWithLimit(file, maxInputBytes);
1044
1042
  const baseInput = removeEnvelope(input);
1045
1043
  const envelopePresence = extractEnvelopeFields(input);
1046
1044
  if (envelopePresence.errors.length > 0) {
@@ -1532,9 +1530,6 @@ function formatGenericErrorLine(error) {
1532
1530
  const prefix = phaseLabel ? `${phaseLabel}: ` : '';
1533
1531
  return `${prefix}${message} [${code}] path=$ span=${span}`;
1534
1532
  }
1535
- function findFile(args) {
1536
- return args.find(arg => !arg.startsWith('--'));
1537
- }
1538
1533
  function findFileWithValueFlags(args, valueFlags) {
1539
1534
  const skip = new Set();
1540
1535
  for (let i = 0; i < args.length; i++) {
@@ -1593,14 +1588,17 @@ function resolveDepthOption(args, flag) {
1593
1588
  return null;
1594
1589
  return Number.parseInt(value, 10);
1595
1590
  }
1591
+ function failInputByteLimit(actualBytes, maxInputBytes) {
1592
+ console.error(`Error: Input size ${actualBytes} bytes exceeds configured limit of ${maxInputBytes} bytes`);
1593
+ process.exit(1);
1594
+ }
1596
1595
  function enforceInputByteLimitOrExit(input, maxInputBytes) {
1597
1596
  if (maxInputBytes === undefined)
1598
1597
  return;
1599
1598
  const actualBytes = Buffer.byteLength(input, 'utf8');
1600
1599
  if (actualBytes <= maxInputBytes)
1601
1600
  return;
1602
- console.error(`Error: Input size ${actualBytes} bytes exceeds configured limit of ${maxInputBytes} bytes`);
1603
- process.exit(1);
1601
+ failInputByteLimit(actualBytes, maxInputBytes);
1604
1602
  }
1605
1603
  function readFile(file) {
1606
1604
  try {
@@ -1611,9 +1609,42 @@ function readFile(file) {
1611
1609
  process.exit(2);
1612
1610
  }
1613
1611
  }
1614
- function readStdin() {
1612
+ function readFileWithLimit(file, maxInputBytes) {
1613
+ if (maxInputBytes !== undefined) {
1614
+ try {
1615
+ const stats = fs.statSync(file);
1616
+ if (stats.isFile() && stats.size > maxInputBytes) {
1617
+ failInputByteLimit(stats.size, maxInputBytes);
1618
+ }
1619
+ }
1620
+ catch (err) {
1621
+ console.error(`Error: Cannot read file: ${file}`);
1622
+ process.exit(2);
1623
+ }
1624
+ }
1625
+ const input = readFile(file);
1626
+ enforceInputByteLimitOrExit(input, maxInputBytes);
1627
+ return input;
1628
+ }
1629
+ function readStdin(maxInputBytes) {
1615
1630
  try {
1616
- return fs.readFileSync(0, 'utf-8');
1631
+ if (maxInputBytes === undefined) {
1632
+ return fs.readFileSync(0, 'utf-8');
1633
+ }
1634
+ const chunks = [];
1635
+ const buffer = Buffer.allocUnsafe(64 * 1024);
1636
+ let actualBytes = 0;
1637
+ while (true) {
1638
+ const bytesRead = fs.readSync(0, buffer, 0, buffer.length, null);
1639
+ if (bytesRead === 0)
1640
+ break;
1641
+ actualBytes += bytesRead;
1642
+ if (actualBytes > maxInputBytes) {
1643
+ failInputByteLimit(actualBytes, maxInputBytes);
1644
+ }
1645
+ chunks.push(Buffer.from(buffer.subarray(0, bytesRead)));
1646
+ }
1647
+ return Buffer.concat(chunks).toString('utf-8');
1617
1648
  }
1618
1649
  catch {
1619
1650
  console.error('Error: Cannot read stdin');