@taqueria/plugin-ligo 0.40.2 → 0.40.4

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/common.ts CHANGED
@@ -38,8 +38,29 @@ export const getInputFilenameAbsPath = (parsedArgs: UnionOpts, sourceFile: strin
38
38
  export const getInputFilenameRelPath = (parsedArgs: UnionOpts, sourceFile: string): string =>
39
39
  join(parsedArgs.config.contractsDir ?? 'contracts', sourceFile);
40
40
 
41
- export const emitExternalError = (err: unknown, sourceFile: string): void => {
41
+ export const formatLigoError = (err: Error): Error => {
42
+ let result = err.message.replace(/Command failed.+?\n/, '');
43
+ if (
44
+ result.includes('An internal error ocurred. Please, contact the developers.')
45
+ && result.includes('Module Contract not found with last Contract.')
46
+ ) {
47
+ result =
48
+ `The contract must be imported with "Contract" as the namespace: #import "path/to/contract.ligo" "Contract"`;
49
+ }
50
+
51
+ err.message = result.replace(
52
+ 'An internal error ocurred. Please, contact the developers.',
53
+ 'The LIGO compiler experienced an internal error. Please contact the LIGO developers.',
54
+ );
55
+
56
+ return err;
57
+ };
58
+
59
+ export const emitExternalError = (errs: unknown[] | unknown, sourceFile: string): void => {
42
60
  sendErr(`\n=== Error messages for ${sourceFile} ===`);
43
- err instanceof Error ? sendErr(err.message.replace(/Command failed.+?\n/, '')) : sendErr(err as any);
44
- sendErr(`\n===`);
61
+ const errors = Array.isArray(errs) ? errs : [errs];
62
+ errors.map(err => {
63
+ err instanceof Error ? sendErr(err.message) : sendErr(err as any);
64
+ });
65
+ sendErr(`===`);
45
66
  };
package/compile.ts CHANGED
@@ -15,21 +15,24 @@ import * as readline from 'readline';
15
15
  import {
16
16
  CompileOpts as Opts,
17
17
  emitExternalError,
18
+ formatLigoError,
18
19
  getInputFilenameAbsPath,
19
20
  getInputFilenameRelPath,
20
21
  getLigoDockerImage,
21
22
  UnionOpts,
22
23
  } from './common';
23
24
 
24
- export type TableRow = { source: string; artifact: string };
25
+ export type TableRow = { source: string; artifact: string; err?: unknown };
25
26
 
26
27
  export type ExprKind = 'storage' | 'default_storage' | 'parameter';
27
28
 
29
+ export type Syntax = 'mligo' | 'jsligo' | 'religo' | 'ligo';
30
+
28
31
  export type ModuleInfo = {
29
32
  moduleName: string;
30
33
  sourceName: string;
31
34
  sourceFile: string;
32
- syntax: 'mligo' | 'jsligo' | 'religo' | 'ligo';
35
+ syntax: Syntax;
33
36
  type: 'file-main' | 'file-entry' | 'module-main' | 'module-entry';
34
37
  };
35
38
 
@@ -217,10 +220,10 @@ const compileExpr =
217
220
  };
218
221
  })
219
222
  .catch(err => {
220
- emitExternalError(err, sourceFile);
221
223
  return {
222
224
  source: module.sourceName,
223
- artifact: `${sourceFile} not compiled`,
225
+ artifact: `${exprName} in ${sourceFile} not compiled`,
226
+ err,
224
227
  };
225
228
  });
226
229
  };
@@ -251,247 +254,118 @@ const getExprNames = (parsedArgs: Opts, sourceFile: string): Promise<string[]> =
251
254
  });
252
255
  };
253
256
 
254
- const compileExprs = (
257
+ const compileExprs = async (
255
258
  parsedArgs: Opts,
256
259
  sourceFile: string,
257
260
  module: ModuleInfo,
258
261
  exprKind: ExprKind,
259
- ): Promise<TableRow[]> =>
260
- getExprNames(parsedArgs, sourceFile)
261
- .then(exprNames => {
262
- if (exprNames.length === 0) return [];
263
- const firstExprName = exprNames.slice(0, 1)[0];
264
- const restExprNames = exprNames.slice(1, exprNames.length);
265
- const firstExprKind = isStorageKind(exprKind) ? 'default_storage' : 'parameter';
266
- const restExprKind = isStorageKind(exprKind) ? 'storage' : 'parameter';
267
- const firstExprResult = compileExpr(parsedArgs, sourceFile, module, firstExprKind)(firstExprName);
268
- const restExprResults = restExprNames.map(compileExpr(parsedArgs, sourceFile, module, restExprKind));
269
- return Promise.all([firstExprResult].concat(restExprResults));
270
- })
271
- .catch(err => {
272
- emitExternalError(err, sourceFile);
273
- return [{
274
- source: module.sourceName,
275
- artifact: `No ${isStorageKind(exprKind) ? 'storage' : 'parameter'} expressions compiled`,
276
- }];
277
- })
278
- .then(results =>
279
- results.length > 0 ? results : [{
280
- source: module.sourceName,
281
- artifact: `No ${isStorageKind(exprKind) ? 'storage' : 'parameter'} expressions found`,
282
- }]
283
- );
262
+ ): Promise<TableRow[]> => {
263
+ // Get expressions from file
264
+ let exprs = [];
265
+ try {
266
+ exprs = await getExprNames(parsedArgs, sourceFile);
267
+ } catch (err) {
268
+ emitExternalError(err, sourceFile);
269
+ return [{
270
+ source: module.sourceName,
271
+ artifact: `No ${isStorageKind(exprKind) ? 'storage' : 'parameter'} expressions compiled`,
272
+ }];
273
+ }
284
274
 
285
- const initContentForStorage = (module: ModuleInfo): string => {
286
- const linkToContract = `#import "${module.sourceFile}" "Contract"\n\n`;
287
- const instruction =
288
- '// Define your initial storage values as a list of LIGO variable definitions, the first of which will be considered the default value to be used for origination later on\n';
289
-
290
- const syntax = (() => {
291
- const pair = [module.syntax, module.type].join('-');
292
- switch (pair) {
293
- case 'mligo-file-main':
294
- return [
295
- '// When this file was created, the smart contract was defined with a main function that was not within a named module. As such, the examples below are written with that assumption in mind.',
296
- '',
297
- '// If your storage is a simple value, you can define it directly',
298
- '// E.g. let storage = 10',
299
- '',
300
- '// For added type-safety, you can reference the type of your storage from the contract',
301
- '// E.g. let storage : Contract.storage = 10',
302
- ];
303
- break;
304
- case 'mligo-file-entry':
305
- return [
306
- '// When this file was created, the smart contract was defined with an entrypoint using `@entry` that was not within a named module. As such, the examples below are written with that assumption in mind.',
307
- '',
308
- '// If your storage is a simple value, you can define it directly',
309
- '// E.g. let storage = 10',
310
- '',
311
- '// For added type-safety, you can reference the type of your storage from the contract',
312
- '// E.g. let storage : Contract.storage = 10',
313
- ];
314
- break;
315
- case 'mligo-module-main':
316
- return [
317
- '// When this file was created, the smart contract was defined with a main function that was within a named module. As such, the examples below are written with that assumption in mind.',
318
- '',
319
- '// If your storage is a simple value, you can define it directly',
320
- '// E.g. let storage = 10',
321
- '',
322
- '// For added type-safety, you can reference the type of your storage from the contract',
323
- `// E.g. let storage : Contract.${module.moduleName}.storage = 10`,
324
- ];
325
- break;
326
- case 'mligo-module-entry':
327
- return [
328
- '// When this file was created, the smart contract was defined with an entrypoint using `@entry` that was within a named module. As such, the examples below are written with that assumption in mind.',
329
- '',
330
- '// If your storage is a simple value, you can define it directly',
331
- '// E.g. let storage = 10',
332
- '',
333
- '// For added type-safety, you can reference the type of your storage from the contract',
334
- `// E.g. let storage : Contract.${module.moduleName}.storage = 10`,
335
- ];
336
- break;
337
- case 'jsligo-file-main':
338
- return [
339
- '// When this file was created, the smart contract was defined with a main function that was not within a namespace. As such, the examples below are written with that assumption in mind.',
340
- `// NOTE: The "storage" type should be exported from the contract file (${module.sourceFile})`,
341
- '',
342
- '// If your storage is a simple value, you can define it directly',
343
- '// E.g. const storage = 10',
344
- '',
345
- '// For added type-safety, you can reference the type of your storage from the contract. This assumes that you have exported your `storage` type from the contract file.',
346
- '// E.g. const storage : Contract.storage = 10',
347
- ];
348
- break;
349
- case 'jsligo-file-entry':
350
- return [
351
- '// When this file was created, the smart contract was defined with an entrypoint using `@entry` that was not within a namespace. As such, the examples below are written with that assumption in mind.',
352
- '',
353
- '// If your storage is a simple value, you can define it directly',
354
- '// E.g. const storage = 10',
355
- '',
356
- '// For added type-safety, you can reference the type of your storage from the contract. This assumes that you have exported your `storage` type from the contract file.',
357
- '// E.g. const storage : Contract.storage = 10',
358
- ];
359
- break;
360
- case 'jsligo-module-main':
361
- return [
362
- '// When this file was created, the smart contract was defined with a main function that was within a namespace. As such, the examples below are written with that assumption in mind.',
363
- `// NOTE: The "storage" type should be exported from the contract file (${module.sourceFile})`,
364
- '',
365
- '// If your storage is a simple value, you can define it directly',
366
- '// E.g. const storage = 10',
367
- '',
368
- '// For added type-safety, you can reference the type of your storage from the contract. This assumes that you have exported your `storage` type from the contract file.',
369
- `// E.g. const storage : Contract.${module.moduleName}.storage = 10`,
370
- ];
371
- break;
372
- case 'jsligo-module-entry':
373
- return [
374
- '// When this file was created, the smart contract was defined with an entrypoint using `@entry` that was within a namespace. As such, the examples below are written with that assumption in mind.',
375
- '',
376
- '// If your storage is a simple value, you can define it directly',
377
- '// E.g. const storage = 10',
378
- '',
379
- '// For added type-safety, you can reference the type of your storage from the contract. This assumes that you have exported your `storage` type from the contract file.',
380
- `// E.g. const storage : Contract.${module.moduleName}.storage = 10`,
381
- ];
382
- break;
383
- default:
384
- return [];
385
- }
386
- })();
387
- return linkToContract + instruction + syntax.join('\n');
275
+ const results = await Promise.all(exprs.map(async (exprName, index) => {
276
+ const compileResult = await compileExpr(
277
+ parsedArgs,
278
+ sourceFile,
279
+ module,
280
+ exprKind === 'storage' && index === 0 ? 'default_storage' : exprKind,
281
+ )(exprName);
282
+ return compileResult;
283
+ }));
284
+
285
+ // Collect errors
286
+ const errors = results.reduce(
287
+ (acc, result) => {
288
+ if (result.err) {
289
+ // If its not an Error object, then just add it to the list
290
+ if (!(result.err instanceof Error)) return [...acc, result.err];
291
+
292
+ // Otherwise, get all ligo errors and ensure that the list is unique
293
+ const ligoErrs = (acc
294
+ .filter(err => err instanceof Error) as Error[])
295
+ .map(err => err.message);
296
+
297
+ const formattedError = formatLigoError(result.err);
298
+
299
+ return (ligoErrs.includes(formattedError.message)) ? acc : [...acc, formattedError];
300
+ }
301
+ return acc;
302
+ },
303
+ [] as unknown[],
304
+ );
305
+
306
+ // Collect table rows
307
+ const retval = results.map(({ source, artifact }) => ({ source, artifact }));
308
+
309
+ if (errors.length) emitExternalError(errors, sourceFile);
310
+
311
+ return retval;
388
312
  };
389
313
 
390
- const initContentForParameter = (module: ModuleInfo): string => {
391
- const linkToContract = `#import "${module.sourceFile}" "Contract"\n\n`;
392
- const instruction = '// Define your parameter values as a list of LIGO variable definitions\n';
393
-
394
- const syntax = (() => {
395
- const pair = [module.syntax, module.type].join('-');
396
- switch (pair) {
397
- case 'mligo-file-main':
398
- return [
399
- '// When this file was created, the smart contract was defined with a main function that was not within a named module. As such, the examples below are written with that assumption in mind.',
400
- '',
401
- '// If your parameter is a simple value, you can define it directly',
402
- '// E.g. let default_parameter = 10',
403
- '',
404
- '// For added type-safety, you can reference the type of your parameter from the contract',
405
- '// E.g. let default_parameter : Contract.parameter = 10',
406
- ];
407
- break;
408
- case 'mligo-file-entry':
409
- return [
410
- '// When this file was created, the smart contract was defined with an entrypoint using `@entry` that was not within a named module. As such, the examples below are written with that assumption in mind.',
411
- '',
412
- '// If your parameter is a simple value, you can define it directly',
413
- '// E.g. let default_parameter = 10',
414
- '',
415
- '// For added type-safety, you can reference the type of your parameter from the contract',
416
- '// E.g. let default_parameter : parameter_of Contract = 10',
417
- ];
418
- break;
419
- case 'mligo-module-main':
420
- return [
421
- '// When this file was created, the smart contract was defined with a main function that was within a named module. As such, the examples below are written with that assumption in mind.',
422
- '',
423
- '// If your parameter is a simple value, you can define it directly',
424
- '// E.g. let default_parameter = 10',
425
- '',
426
- '// For added type-safety, you can reference the type of your parameter from the contract',
427
- `// E.g. let default_parameter : Contract.${module.moduleName}.parameter = 10`,
428
- ];
429
- break;
430
- case 'mligo-module-entry':
431
- return [
432
- '// When this file was created, the smart contract was defined with an entrypoint using `@entry` that was within a named module. As such, the examples below are written with that assumption in mind.',
433
- '',
434
- '// If your parameter is a simple value, you can define it directly',
435
- '// E.g. let default_parameter = 10',
436
- '',
437
- '// For added type-safety, you can reference the type of your parameter from the contract',
438
- `// E.g. let default_parameter : parameter_of Contract.${module.moduleName} = 10`,
439
- ];
440
- break;
441
- case 'jsligo-file-main':
442
- return [
443
- '// When this file was created, the smart contract was defined with a main function that was not within a namespace. As such, the examples below are written with that assumption in mind.',
444
- `// NOTE: The "parameter" type should be exported from the contract file (${module.sourceFile})`,
445
- '',
446
- '// If your parameter is a simple value, you can define it directly',
447
- '// E.g. const default_parameter = 10',
448
- '',
449
- '// For added type-safety, you can reference the type of your parameter from the contract',
450
- '// E.g. const default_parameter : Contract.parameter = 10',
451
- ];
452
- break;
453
- case 'jsligo-file-entry':
454
- return [
455
- '// When this file was created, the smart contract was defined with an entrypoint using `@entry` that was not within a namespace. As such, the examples below are written with that assumption in mind.',
456
- '',
457
- '// If your parameter is a simple value, you can define it directly',
458
- '// E.g. const default_parameter = 10',
459
- '',
460
- '// For added type-safety, you can reference the type of your parameter from the contract',
461
- '// E.g. const default_parameter : parameter_of Contract = 10',
462
- ];
463
- break;
464
- case 'jsligo-module-main':
465
- return [
466
- '// When this file was created, the smart contract was defined with a main function that was within a namespace. As such, the examples below are written with that assumption in mind.',
467
- `// NOTE: The "parameter" type should be exported from the contract file (${module.sourceFile})`,
468
- '',
469
- '// If your parameter is a simple value, you can define it directly',
470
- '// E.g. const default_parameter = 10',
471
- '',
472
- '// For added type-safety, you can reference the type of your parameter from the contract',
473
- `// E.g. const default_parameter : Contract.${module.moduleName}.parameter = 10`,
474
- ];
475
- break;
476
- case 'jsligo-module-entry':
477
- return [
478
- '// When this file was created, the smart contract was defined with an entrypoint using `@entry` that was within a namespace. As such, the examples below are written with that assumption in mind.',
479
- '',
480
- '// If your parameter is a simple value, you can define it directly',
481
- '// E.g. const default_parameter = 10',
482
- '',
483
- '// For added type-safety, you can reference the type of your parameter from the contract',
484
- `// E.g. const default_parameter : parameter_of Contract.${module.moduleName} = 10`,
485
- ];
486
- break;
487
- default:
488
- return [];
489
- }
490
- })();
314
+ // Helper function to get the initial message based on the pair value
315
+ const getInitialMessage = (pair: string, module: ModuleInfo) => {
316
+ const messages = {
317
+ 'mligo-file-main':
318
+ `// When this file was created, the smart contract was defined with a main function that was not within a named module. As such, the examples below are written with that assumption in mind.`,
319
+ 'mligo-file-entry':
320
+ `// When this file was created, the smart contract was defined with an entrypoint using \`@entry\` that was not within a named module. As such, the examples below are written with that assumption in mind.`,
321
+ 'mligo-module-main':
322
+ `// When this file was created, the smart contract was defined with a main function that was within a named module. As such, the examples below are written with that assumption in mind.`,
323
+ 'mligo-module-entry':
324
+ `// When this file was created, the smart contract was defined with an entrypoint using \`@entry\` that was within a named module. As such, the examples below are written with that assumption in mind.`,
325
+ 'jsligo-file-main':
326
+ `// When this file was created, the smart contract was defined with a main function that was not within a namespace. As such, the examples below are written with that assumption in mind.\n`
327
+ + `// NOTE: The "storage" type should be exported from the contract file (${module.sourceFile})`,
328
+ 'jsligo-file-entry':
329
+ `// When this file was created, the smart contract was defined with an entrypoint using \`@entry\` that was not within a namespace. As such, the examples below are written with that assumption in mind.`,
330
+ 'jsligo-module-main':
331
+ `// When this file was created, the smart contract was defined with a main function that was within a namespace. As such, the examples below are written with that assumption in mind.\n`
332
+ + `// NOTE: The "storage" type should be exported from the contract file (${module.sourceFile})`,
333
+ 'jsligo-module-entry':
334
+ `// When this file was created, the smart contract was defined with an entrypoint using \`@entry\` that was within a namespace. As such, the examples below are written with that assumption in mind.`,
335
+ // ... any other combinations
336
+ } as Record<string, string>;
337
+
338
+ return messages[pair] || '// This file was created by Taqueria.';
339
+ };
340
+
341
+ // Helper function to get a common message
342
+ const getCommonMsg = (langType: Syntax, listType: ExprKind) => {
343
+ const varKeyword = langType === 'mligo' ? 'let' : 'const';
344
+ const commonMsgForStorage = `// IMPORTANT: We suggest always explicitly typing your storage values:\n`
345
+ + `// E.g.: \`${varKeyword} storage: int = 10\` or \`${varKeyword} storage: Contract.storage = 10\``;
491
346
 
492
- return linkToContract + instruction + syntax.join('\n');
347
+ const commonMsgForParameter = `// IMPORTANT: We suggest always explicitly typing your parameter values:\n`
348
+ + `// E.g.: \`${varKeyword} parameter: int = 10\` or \`${varKeyword} parameter: Contract.parameter = 10\``;
349
+
350
+ return listType === 'storage' ? commonMsgForStorage : commonMsgForParameter;
351
+ };
352
+
353
+ // Main function to get the content for storage or parameter
354
+ const getContent = (moduleInfo: ModuleInfo, listType: ExprKind) => {
355
+ const linkToContract = `#import "${moduleInfo.sourceFile}" "Contract"`;
356
+ const pair = `${moduleInfo.syntax}-${moduleInfo.type}`;
357
+ const initialMsg = getInitialMessage(pair, moduleInfo);
358
+ const commonMsg = getCommonMsg(moduleInfo.syntax, listType);
359
+
360
+ return `${linkToContract}\n\n${initialMsg}\n\n${commonMsg}`;
493
361
  };
494
362
 
363
+ // Usage for storage list
364
+ const initContentForStorage = (moduleInfo: ModuleInfo) => getContent(moduleInfo, 'storage');
365
+
366
+ // Usage for parameter list
367
+ const initContentForParameter = (moduleInfo: ModuleInfo) => getContent(moduleInfo, 'parameter');
368
+
495
369
  export const compileContractWithStorageAndParameter = async (
496
370
  parsedArgs: Opts,
497
371
  sourceFile: string,
@@ -499,6 +373,7 @@ export const compileContractWithStorageAndParameter = async (
499
373
  ): Promise<TableRow[]> => {
500
374
  const contractCompileResult = await compileContract(parsedArgs, sourceFile, module);
501
375
  if (contractCompileResult.artifact === COMPILE_ERR_MSG) return [contractCompileResult];
376
+ debugger;
502
377
 
503
378
  const storageListFile = `${module.moduleName}.storageList${extractExt(sourceFile)}`;
504
379
  const storageListFilename = getInputFilenameAbsPath(parsedArgs, storageListFile);