The code above passed in a transaction to extractContractName() method and triggers error below:
kerrywei@kerrys-mbp-2 cadut-example % node app.js
/Users/kerrywei/repos/cadut-example/node_modules/flow-cadut/dist/main.js:1
var t=require("@onflow/config"),n=require("@onflow/types"),r=require("@onflow/fcl");function e(t){if(t&&t.t)return t;var n=Object.create(null);return t&&Object.keys(t).forEach(function(r){if("default"!==r){var e=Object.getOwnPropertyDescriptor(t,r);Object.defineProperty(n,r,e.get?e:{enumerable:!0,get:function(){return t[r]}})}}),n.default=t,n}var o=e(n),c=e(r);const s={emulator:{FlowToken:"0xee82856bf20e2aa6",FungibleToken:"0x0ae53cb6e3f42a79"},testnet:{FlowToken:"0x7e60df042a9c0868",FungibleToken:"0x9a0766d93b6608b7",LockedTokens:"0x95e019a17d0e23d7",StakingProxy:"0x7aad92e5a0715d21",FUSD:"0xe223d8a629e49c68"},mainnet:{FlowToken:"0x1654653399040a61",FungibleToken:"0xf233dcee88fe0abe",LockedTokens:"0x8d0e87b65159ae63",StakingProxy:"0x62430cf28c26d095",FUSD:"0x3c5959b568896393"}},u={mainnet:"https://access-mainnet-beta.onflow.org",testnet:"https://access-testnet.onflow.org",emulator:"http://localhost:8080"},i=function(){try{return Promise.resolve(function(){try{return Promise.resolve(t.config().get("ix.env")).then(function(t){return t||"emulator"})}catch(t){return Promise.reject(t)}}()).then(function(t){return s[t]||s.emulator})}catch(t){return Promise.reject(t)}},a=t=>t.split(/\s/).map(t=>t.replace(/\s/g,"")).filter(t=>t.length>0&&"import"!==t&&"from"!==t),f=(t,n)=>{const[r,e]=n;return t[r]=e,t},l=t=>t&&0!==t.length?t.split("\n").filter(t=>t.includes("import")).map(a).reduce(f,{}):{},p=(t,n={})=>{const r=l(t),e=[];for(const t in r)!n[t]&&Object.prototype.hasOwnProperty.call(r,t)&&e.push(t);return e},m=(t=[],n="")=>{const r="Missing imports for contracts:";console.error(n?`${n} ${r}`:r,t)},d=/(\s*import\s*)([\w\d]+)(\s+from\s*)([\w\d".\\/]+)/g,x=(t,n,r=!0)=>t.replace(d,(t,e,o,c,s)=>{const u=r?o:s;return`${e}${o} from ${(n instanceof Function?n(u):n[u])||s}`}),g=t=>{const[n]=t.split("");return n.toUpperCase()+t.slice(1)},h=t=>{switch(!0){case t.indexOf("//")>=0:return"//";case t.indexOf("/")>=0:return"/";case t.indexOf("\\")>=0:return"\\";default:return""}},P=t=>t.replace(/\s+/g," "),w=t=>t.split(",").map(t=>t.replace(/\s*/g,"")).filter(t=>""!==t),y=t=>t.replace(/(\/\*[\s\S]*?\*\/)|(\/\/.*)/g,""),v=(t,n)=>{const r=y(t),e=P(r.replace(/[\n\r]/g,""));if(e){const t=new RegExp(n,"g").exec(e);if(t)return""===t[1]?[]:w(t[1])}return[]},b=t=>v(t,"(?:prepare\\s*\\(\\s*)([^\\)]*)(?:\\))"),$=t=>v(t,"(?:fun\\s+main\\s*\\(\\s*)([^\\)]*)(?:\\))"),S=t=>v(t,"(?:transaction\\s*\\(\\s*)([^\\)]*)(?:\\))"),k=t=>{const n=y(t).replace(/(resource|struct)\s+\w+\s*{[\s\S]+?}/g,""),r=/(?:access\(\w+\)|pub)\s+contract\s+(?:interface)*\s*(\w*)(\s*{[.\s\S]*init\s*\((.*?)\)[.\s\S]*})?/g.exec(n);if(r.length<2)throw new Error("Contract Error: can't find name of the contract");return{contractName:r[1],args:r[3]||""}},F=t=>{const n=y(t);if(/transaction\s*(\(\s*\))*\s*/g.test(n)){const t=b(n),r=S(n);return{type:"transaction",signers:t.length,args:r}}if(/pub\s+fun\s+main\s*/g.test(n))return{type:"script",args:$(n)};if(/\w+\s+contract\s+(\w*\s*)\w*/g.test(n)){const{contractName:t,args:r}=k(n);return{type:"contract",signers:1,args:r,contractName:t}}return{type:"unknown"}},E=t=>!t||"string"!=typeof t,T=t=>!E(t)&&(t.startsWith("Int")||t.startsWith("UInt")||t.startsWith("Word")),A=t=>{if(E(t))return!1;const n=t.replace(/\s/g,"");return n.startsWith("[")&&n.endsWith("]")},N=t=>{if(E(t))return!1;const n=t.replace(/\s/g,"");return n.startsWith("{")&&n.endsWith("}")},j=t=>A(t)||N(t);function I(t,n,r){if(!t.s){if(r instanceof O){if(!r.s)return void(r.o=I.bind(null,t,n));1&n&&(n=r.s),r=r.v}if(r&&r.then)return void r.then(I.bind(null,t,n),I.bind(null,t,2));t.s=n,t.v=r;const e=t.o;e&&e(t)}}const O=function(){function t(){}return t.prototype.then=function(n,r){const e=new t,o=this.s;if(o){const t=1&o?n:r;if(t){try{I(e,1,t(this.v))}catch(t){I(e,2,t)}return e}return this}return this.o=function(t){try{const o=t.v;1&t.s?I(e,1,n?n(o):o):r?I(e,1,r(o)):I(e,2,o)}catch(t){I(e,2,t)}},e},t}(),U={ARGUMENT:"argument"},L=function(t){try{return Promise.resolve(r.config().get("ix.plugins")).then(function(n){const r=(n||{})[t];return!!(r&&r.length>0)&&r})}catch(t){return Promise.reject(t)}};function M(t,n,r){if(!t.s){if(r instanceof _){if(!r.s)return void(r.o=M.bind(null,t,n));1&n&&(n=r.s),r=r.v}if(r&&r.then)return void r.then(M.bind(null,t,n),M.bind(null,t,2));t.s=n,t.v=r;const e=t.o;e&&e(t)}}const _=function(){function t(){}return t.prototype.then=function(n,r){const e=new t,o=this.s;if(o){const t=1&o?n:r;if(t){try{M(e,1,t(this.v))}catch(t){M(e,2,t)}return e}return this}return this.o=function(t){try{const o=t.v;1&t.s?M(e,1,n?n(o):o):r?M(e,1,r(o)):M(e,2,o)}catch(t){M(e,2,t)}},e},t}(),q=t=>t.split(/(\w+)\s*:\s*([\w{}[\]:\s?]*)/).filter(t=>""!==t).map(t=>t.replace(/\s*/g,"")),C=t=>q(t)[1],D=t=>/{(.*)}/.exec(t)[1].split(/([^:]*):(.*)/).map(t=>t.replace(/\s/g,"")).filter(t=>t),R=t=>/\[(.*)\]/.exec(t)[1].replace(/\s+/g,""),B=t=>!E(t)&&(t.includes("?")?o.Optional(o[(t=>t.slice(0,-1))(t)]):o[t]),H=t=>{if(j(t))switch(!0){case A(t):{const n=R(t);return o.Array(H(n))}case N(t):{const[n,r]=D(t),e={key:H(n),value:H(r)};return o.Dictionary(e)}default:return B(t)}return B(t)},z=function(t,n){try{return Promise.resolve(L(U.ARGUMENT)).then(function(r){function e(){let t;const n=H(s);switch(!0){case(t=>{if(E(t))return!1;let n=t.endsWith("?")?t.slice(0,-1):t;return T(n)||(t=>"String"===t)(n)||(t=>"Character"===t)(n)||(t=>"Bool"===t)(n)})(s):return c.arg(o,n);case(t=>!E(t)&&(t.startsWith("Fix64")||t.startsWith("UFix64")))(s):return null===o?c.arg(null,n):(isNaN(parseFloat(o))&&(t=>{throw new Error("Type Error: Expected proper value for fixed type")})(),c.arg(parseFloat(o).toFixed(8),n));case(t=>"Address"===t||"Address?"===t)(s):{const t=null==(p=o)?null:"0x"+(t=>null==t?null:t.replace(/^0x/,""))(p);return c.arg(t,n)}case A(s):{function r(r){return t?r:c.arg(o,n)}const e=R(s),u=function(){if(j(e))return Promise.resolve(Promise.all(o.map(function(t){try{return Promise.resolve(z(e,t)).then(function({value:t}){return t})}catch(t){return Promise.reject(t)}}))).then(function(r){return t=1,c.arg(r,n)})}();return u&&u.then?u.then(r):r(u)}case N(s):{function e(){return c.arg(p,n)}const[t,r]=D(s),p=[],m=Object.keys(o),d=(u=m,i=function(n){function e(){const n=T(t)?parseInt(c):c;p.push({key:n,value:s})}const c=m[n];let s;const u=function(){if(j(r))return Promise.resolve(z(r,o[c]).value).then(function(t){s=t});s=o[c]}();return u&&u.then?u.then(e):e()},l=-1,function t(n){try{for(;++l<u.length;)if((n=i(l))&&n.then){if(!((r=n)instanceof _&&1&r.s))return void n.then(t,f||(f=M.bind(null,a=new _,2)));n=n.v}a?M(a,1,n):a=n}catch(t){M(a||(a=new _),2,t)}var r}(),a);return d&&d.then?d.then(e):e()}default:throw`${s} is not supported`}var u,i,a,f,l,p}let o=n,s=t;const u=function(){if(r)return Promise.resolve(function(t,n){try{function r(){return{type:i,value:a}}let i=t.type,a=t.value;const f=(e=n,o=function(t){const{resolver:r}=n[t];return Promise.resolve(r(i,a)).then(function(t){i=t.type,a=t.value})},u=-1,function t(n){try{for(;++u<e.length;)if((n=o(u))&&n.then){if(!((r=n)instanceof O&&1&r.s))return void n.then(t,s||(s=I.bind(null,c=new O,2)));n=n.v}c?I(c,1,n):c=n}catch(t){I(c||(c=new O),2,t)}var r}(),c);return Promise.resolve(f&&f.then?f.then(r):r())}catch(t){return Promise.reject(t)}var e,o,c,s,u}({type:t,value:n},r)).then(function(t){o=t.value,s=t.type})}();return u&&u.then?u.then(e):e()})}catch(t){return Promise.reject(t)}},G=function(t=[],n){try{if(t.length>n.length)throw new Error("Not enough arguments");return Promise.all(n.map(function(n,r){try{return Promise.resolve(z(t[r],n)).then(function(t){var n;return(n=t).xform.asArgument(n.value),t})}catch(t){return Promise.reject(t)}}))}catch(t){return Promise.reject(t)}},W=function(t,n=[]){try{const r=F(t).args.map(C);return G(r,n)}catch(t){return Promise.reject(t)}},J=function(t,n){try{if(0===t.length)return Promise.resolve([]);const r=t[0];return Array.isArray(r)&&r.length>0&&r[r.length-1].asArgument?Promise.resolve((t=>t.reduce((t,n)=>[...t,...((t,n)=>{const r=t[t.length-1];return t.slice(0,-1).map(t=>((t,n)=>c.arg(t,n))(t,r))})(n)],[]))(t)):W(n,t)}catch(t){return Promise.reject(t)}};function K(t,n){try{var r=t()}catch(t){return n(t)}return r&&r.then?r.then(void 0,n):r}const Q=function(n,r){try{const{code:e,cadence:o,args:s,addressMap:u,limit:a,processed:f}=n,l=e||o;return Promise.resolve(i()).then(function(o){function i(){return Promise.resolve(t.config().get("ix.executionLimit")).then(function(t){if(d.push(c.limit(a||t||100)),"transaction"===r){const{proposer:t,payer:r,signers:e=[]}=n,o=0===e.length?[r]:e,s=t||r;d.push(c.payer(r)),d.push(c.proposer(s)),d.push(c.authorizations(o))}return c.send(d)})}const p={...o,...u},m=f?l:x(l,p),d="script"===r?[c.script(m)]:[c.transaction(m)],g=function(){if(s)return Promise.resolve(J(s,e)).then(function(t){d.push(c.args(t))})}();return g&&g.then?g.then(i):i()})}catch(t){return Promise.reject(t)}},V=function(t){const{raw:n=!1}=t;return Promise.resolve(K(function(){return Promise.resolve(Q(t,"script")).then(function(t){return n?[t.encodedData,null]:Promise.resolve(c.decode(t)).then(function(t){return[t,null]})})},function(t){return[null,t]}))},X=function(t){const{wait:n="seal"}=t;return Promise.resolve(K(function(){return Promise.resolve(Q(t,"transaction")).then(function(t){let r;function e(n){return r?n:[t.transactionId,null]}const o=function(){if(n){const e=(t=>{if("string"==typeof t){const n=t.toLowerCase();if(n.includes("final"))return"onceFinalized";if(n.includes("exec"))return"onceExecuted";if(n.includes("seal"))return"onceSealed"}return console.log(`โ ๏ธ Status value "${t}" is not supported. Reverting to "onceSealed"`),"onceSealed"})(n);return Promise.resolve(c.tx(t)[e]()).then(function(n){const e={txId:t,...n};return r=1,[e,null]})}}();return o&&o.then?o.then(e):e(o)})},function(t){return[null,t]}))},Y=function(t){try{const{name:n,to:r,payer:e,proposer:o,code:c,update:s=!1,processed:u=!1,addressMap:i={}}=t,a=u?c:x(c,i),f=s?"\n transaction(name: String, code: String) {\n prepare(acct: AuthAccount){\n let decoded = code.decodeHex()\n \n acct.contracts.add(\n name: name,\n code: decoded,\n )\n }\n }\n ":"\n transaction(name: String, code: String){\n prepare(acct: AuthAccount){\n let decoded = code.decodeHex()\n \n if acct.contracts.get(name: name) == nil {\n acct.contracts.add(name: name, code: decoded)\n } else {\n acct.contracts.update__experimental(name: name, code: decoded)\n }\n }\n }\n",l=Buffer.from(a,"utf8").toString("hex");let p=r,m=r;return e&&(m=e,p=o||e),X({payer:m,proposer:p,signers:[r],code:f,args:[n,l]})}catch(t){return Promise.reject(t)}};exports.CONTRACT="contract",exports.PLUGIN_TYPES=U,exports.SCRIPT="script",exports.TRANSACTION="transaction",exports.argType=C,exports.capitalizeFirstLetter=g,exports.collapseSpaces=P,exports.deployContract=Y,exports.executeScript=V,exports.extract=v,exports.extractContractName=t=>{const n=y(t).replace(/\r\n|\n|\r/g," "),r=/\w+\s+contract\s+(?:interface)*\s*(\w*)/g.exec(n);if(r.length<2)throw new Error("Contract Error: can't find name of the contract");return r[1]},exports.extractContractParameters=k,exports.extractImports=l,exports.extractScriptArguments=$,exports.extractSigners=b,exports.extractTransactionArguments=S,exports.generateSchema=w,exports.getArrayType=R,exports.getDictionaryTypes=D,exports.getEnvironment=i,exports.getPlugins=L,exports.getSplitCharacter=h,exports.getTemplateInfo=F,exports.mapArgument=z,exports.mapArguments=G,exports.mapValuesToCode=W,exports.missingImports=p,exports.mutate=X,exports.query=V,exports.registerPlugin=function(t){try{const{type:n}=t;return Promise.resolve(r.config().get("ix.plugins")).then(function(e){const o=e||{},c=o[n]||[];return Promise.resolve(r.config().put("ix.plugins",{...o,[n]:[...c,t]})).then(function(){})})}catch(t){return Promise.reject(t)}},exports.replaceImportAddresses=x,exports.report=m,exports.reportArguments=(t,n,r="")=>{if(n>t){const e=`Incorrect number of arguments: found ${t} of ${n}`;console.error(r?`${r} ${e}`:e)}},exports.reportMissing=(t="items",n,r,e="")=>{if(r!==n){const o=`Incorrect number of ${t}: found ${n} of ${r}`;console.error(e?`${e} ${o}`:o)}},exports.reportMissingImports=(t,n,r="")=>{const e=p(t,n);e.length>0&&m(e,r)},exports.resolveArguments=J,exports.sendTransaction=X,exports.setEnvironment=function(n="emulator",r={}){try{const e=n.toLowerCase();if(!s[e])throw new Error(`Provided value "${e}" is not supported. Try "emulator", "testnet" or "mainnet". Default: "emulator"`);const{port:o,endpoint:c,limit:i}=r,a="emulator"===e&&o?`http://localhost:${o}`:u[e],f=c||a;return Promise.resolve(t.config().put("ix.env",e)).then(function(){function n(){return Promise.resolve(t.config().put("accessNode.api",f)).then(function(){})}const r=function(){if(i)return Promise.resolve(t.config().put("ix.executionLimit",i)).then(function(){})}();return r&&r.then?r.then(n):n()})}catch(t){return Promise.reject(t)}},exports.splitArgs=q,exports.trimAndSplit=(t,n,r)=>r?t.replace(n,"").split(r):t.replace(n,"").split(h(t)),exports.underscoreToCamelCase=t=>t.replace(/-/g,"_").split("_").map((t,n)=>n>0?g(t):t).join(""),exports.updateContract=function(t){try{return Y({...t,update:!0})}catch(t){return Promise.reject(t)}};
TypeError: Cannot read properties of null (reading 'length')
at Object.exports.extractContractName (/Users/kerrywei/repos/cadut-example/node_modules/flow-cadut/dist/main.js:1:11064)
at Object.<anonymous> (/Users/kerrywei/repos/cadut-example/app.js:31:9)
at Module._compile (node:internal/modules/cjs/loader:1095:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1147:10)
at Module.load (node:internal/modules/cjs/loader:975:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
at node:internal/main/run_main_module:17:47
Node.js v17.0.1
kerrywei@kerrys-mbp-2 cadut-example %
This is a minor issue (as we assume most people will pass in right type of transaction/script/contract), however, rather than showing "TypeError: Cannot read properties of null (reading 'length')", we can return a more explicit error type and error message