Anyone has the experience in using TypeScript with...
# sdf
d
Anyone has the experience in using TypeScript with SDF CLI?
s
I use TypeScript exclusively. With SDF I just upload both the .TS and .JS files to file cabinet. Not sure what you mean by using TS with the SDF cli, perhaps elaborate?
d
Hi @stalbert! I’m trying to create an environment to develop on TS, do some unit tests with Jest and then deploy to NS js files.
s
sounds good. I don't see how TS conflicts with SDF - just deploy the compiled JS files or optionally both the TS and JS via
deploy.xml
I upload both the TS and JS even though NS only cares about the JS of course.
just to have the TS there as an additional lightweight backup (also 'backed up' in git server)
d
How do you compile TS files to have format for NetSuite to understand?
s
for SS2.1, I compile to a ES2018 target
for SS 2.0, ES5
also, I compile to UMD module format - this allows the code to run both in NS and in jest tests (nodejs)
d
Oh, I see. So UMD must be set in tsconfig.json?
In compilerOptions -> module?
s
yes, here I'll paste an example complete tsconfig.json I use
d
Great, thank you!
s
first, package.json is useful as netsuite-types is crucial
tsconfig.json
looking at the above, I notice the
lib
section may need to be updated if you are using bulit-ins from newer ECMAScript versions
d
Thank you! Should these files be copied to each new project I create?
In my file Logger.ts I have the following import:
Copy code
import * as log from "N/log"
When I try to compile the file I get: libs % tsc Logger.ts Logger.ts522 - error TS2307: Cannot find module ‘N/log’ or its corresponding type declarations. 5 import * as log from “N/log”
s
that is handled by the
paths
section of tsconfig.json. It's assuming you have done
npm install
beforehand
d
Sure
s
and that you have a dependency on @hitc/netsuite-types as shown in the package.json I provided?
d
Yes, and IDE sees that file, so when I hover under “N/log” I see …/sdfProjects/libs/node_modules/@hitc/netsuite-types/N/log.d.ts
s
yes, that should pint to the netsuite-types at compile time
you might try running TSC locally to ensure the IDE isn't doing something wonky
e.g.
node_modules/.bin/tsc
(assuming you are indicating a specific version of TS in your package.json, as my example showed?)
d
I just deleted node_modules and relaunched npm install. but still the same: node_modules/.bin/tsc Logger.ts Logger.ts522 - error TS2307: Cannot find module ‘N/log’ or its corresponding type declarations. 5 import * as log from “N/log”
s
try running
tsc
without passing the filename
d
node_modules/.bin/tsc error TS5055: Cannot write file ‘/Users/dmitrijmasanov/systems-new/systems/netsuite/sdfProjects/libs/babel.config.js’ because it would overwrite input file. error TS5055: Cannot write file ‘/Users/dmitrijmasanov/systems-new/systems/netsuite/sdfProjects/libs/jest.config.js’ because it would overwrite input file. error TS5055: Cannot write file ‘/Users/dmitrijmasanov/systems-new/systems/netsuite/sdfProjects/libs/suitecloud.config.js’ because it would overwrite input file.
s
hmm, turn off the
allowjs:true
option in tsconfig.json
the point of not including the filename is if you pass a filename to
tsc
it compiles ONLY the files you pass on the command line - which will only succeed if you have no dependencies in your source file at all. In your case you do have dependencies (on N/log for example) so it fails to find definitions for that... since all you gave the compiler was the
Logger.ts
file alone.
when you run
tsc
without a file argument, it uses
tsconfig.json
to drive which files are including in the compilation.
d
Oh, I see. Then ok no errors for now.
s
yay
of course, when it comes to loggers, I highly recommend the NFT logger over the native logger 🙂 but that's another topic
d
Great, thank you! The next step for me is to launch a test. Do you launch it as .ts or .js?
s
if you are using
ts-jest
I let it do most of the work
d
Yes, I’m using ts-jest.
Just tried and get the error again: Test suite failed to run Cannot find module ‘N/log’ from ‘Logger.js’
s
In typical unit testing style, you'll need to provide mocks/stubs for any dependencies.
d
Oh, I see, yes, I read about that.
s
since the goal of unit tests is to test your code, not dependencies you're supposed to mock out any dependencies, leaving only your system-under-test code to be interrogated.
I think the node SDF cli comes with a mocking approach
d
Will try to use mocks
s
I'm still evolving how I want to use mocks with SuiteScript
but I have tended to mock out each module with
jest.fn()
you can get some default (mock everything) behavior IIRC by just putting an empty file like
log.js
under
__mocks__
per the jest documentation
d
Hm. That’s interesting
s
unit testing is one thing NFT makes easier - since it exposes a straightforward object syntax for NS records you don't have to constantly mock a bunch of NS functions. You just pass a simple js object to a function to simulate a NS record.
example
d
Never heard about NFT, will learn, thank you!
s
the
save()
method does need a little
jest.fn()
but the rest is just a plain object literal. It makes setting up test data easier and more clear (imho)
d
For now
Copy code
__mocks__.N.logs.js
file solved the issue
👍 1
e
You good @Dmitry Masanov? Happy to help if you need it. Welcome to TypeScript by the way!
d
Thank you @stalbert! The test passed!
Hi @ExtendApps Inc. Yes, thank you, every is fine for now. I think I’ll have more questions when will try to write a real script.
s
once you get through the one-time setup, TypeScript certainly makes SuiteScript development more pleasant (imho)
e
That's the understatement of the year @stalbert ^^^ (and its only January!)
s
lol yeah, suppose you're right. Though a lot of folks here either have never tried it (don't know what they're missing) or perhaps actively don't want things to be pleasant?
d
Agree. I’ve been using TS from the very beginning of my SuiteScript developer career and I have no idea how to live without it.
r
@Dmitry Masanov & @stalbert Do you have any specific tutorial to help setup from scratch a TypeScript based NS dev environment. We are looking to grow our internal development function and feel using TypeScript will be better in the long run.
r
I am also interested in getting started with TypeScript! Any suggestion is welcome 🙂
d
I don’t have a tutorial for now, but I’m in process of building the environment, so once it completed, I can share the steps
🍻 1
👍 1
Hi @stalbert. Can you please help me a bit more? I’m trying to have my sdf projects to use some common libs. So, I have a folder sdfProjects with all the projects I’m going to have. Inside this projects I have something like FirstProject, SecondProject, etc. And also I have “libs” folder in the same sdfProject where I keep my libraries. So, in sdfProjects -> SecondProject I have the following in tsconfig.json:
Copy code
{
  "compilerOptions": {
    "allowJs": false,
    "strictNullChecks": true,
    "module": "umd",
    "moduleResolution": "node",
    "target": "ES2018",
    "sourceMap": false,
    "newLine": "LF",
    "experimentalDecorators": true,
    "baseUrl": "./",
    "outDir": "src/FileCabinet/SuiteScripts/SecondProject",
    "lib":["es5","es2015.promise", "dom"],
    "skipLibCheck": true,
    "esModuleInterop": true,
    "paths": {
      "N/*": [
        "node_modules/@hitc/netsuite-types/N/*"
      ],
      "libs/*": [
        "../libs/*"
      ],
    }
  },
  "exclude":[
    "node_modules",  "__mocks__"],
}
In the SecondProject root I have usev_simple_script.ts where I import, for example, Logger from libs. But when I compile the SecondProject, I get the following folders: sdfProjects/SecondProject/src/FileCabinet/SuiteScripts/SecondProject sdfProjects/SecondProject/src/FileCabinet/SuiteScripts/*SecondProject/SecondProject* (where usev_simple_script.js resides) sdfProjects/SecondProject/src/FileCabinet/SuiteScripts/SecondProject/libs (with all compiled libs)
Do you know if it is possible make TS not to create another one SecondProject folder?
s
if the tsconfig.json is already in SecondProject/ just don't specify an
outDir
?
d
Yes, I have it:
Copy code
"outDir": "src/FileCabinet/SuiteScripts/SecondProject",
s
have you tried removing that property? by default it should drop the files in the same folder as tsconfig.json IIRC
d
I’ve just tried, but in this scenario I only have usev_simple_script.js in SecondProject root folder, but no libs
s
try
"outDir": "."
?
is your goal to get the libraries and usev_simple_script all output to a common folder?
d
Yes, this time lib folder is also added to the SecondProject
s
My suggestion would be to simplify your project structure if possible, and if not recognize that while TSC has the ability to provide some flexibility on compiled output locations if you need to get fancy you probably want a separate build tool. Even a simple shell script would do, or could use
gulp
or similar.
d
Yes, something like that. I want to have them in one folder and then use project:deploy to send to NS
s
I don't know if using "." as your outDir will pull the compiled libs into your main folder but it's worth a quick try
d
It pulled compiled libs again, but also created another SecondProject folder inside the SecondProject folder.
And how do you use common libraries in your projects?
Also, when I just put all the files in one folder, I still cannot create a script record in Netsuite due to the error: “MODULE_DOES_NOT_EXIST\“,\“message\“:\“Module does not exist: /Logger.js\”
Oh, found the reason. It should be define([“require”, “exports”, “N/log”, “./Logger”], not define([“require”, “exports”, “N/log”, “Logger”]. Is there a way to make ./Logger instead of just “Logger”?
s
try `import`ing it as "./Logger" rather than "Logger".
d
Great, that works, thank you!
s
For libraries common to all projects (e.g. NFT, lodash) we put it in a common location and scripts refer to that same location even across projects.
libaries shared only across a subset of files - e.g. for a given business project, we put libs in a folder alongside the other script files for that project.
d
Ok, I see thank you. I’ll do the same
s
Also related, at least so far I've not been creating separate SDF projects for every little thing. In general I'll use a single SDF project and modify the
deploy.xml
over the lifespan of different efforts
d
Yeah, I see. For now I’m building a process from scratch, so I believe it is a good idea to have each feature as a single projects with its libs and tests
s
many business 'projects' are a single script. Only when things start to get more complicated with multiple files for a single project do I switch to putting it in a subfolder potentially with its own SDF
I use branches to isolate work, then tag the repo after merging back into mainline when deployed to production. The tag gives us an easy way to refer back to exactly what was deployed for that release (e.g. tag
release-foo
will have deploy.xml configured exactly as needed for that particular release). This has been a compromise to keep our SDF project count small and usually stick with a simple single deploy.xml that just evolves over time. At any point in time deploy.xml only contains a small subset of the total - only those artifacts needing deployment for a specific effort/customization.
I know others take a different-SDF-project-for-each-feature approach, and a few have tried one-huge-SDF-project-to-rule-them-all. I've found the approach above to be a livable balance between those extremes.
the reason mention all that is it may be that my overall directory structure and SDF usage may make it easier to keep TypeScript happy.
d
Yeah. My goal is to have projects as independent as possible. So when I break one of them, I can be sure all other are still working as expected.
s
one last note - if you are keeping lots of different
tsconfig.json
files around, you might want to take advantage of the inheritance feature so that you can define common properties in a top level
tsconfig.json
and others can just define what they need.
NS is somewhat unique in that projects are not entirely independent - there can be indirect dependencies due to the shared nature of NS.
d
That’s why I’m trying to split them as much as possible.
s
my point is, splitting in an SDF sense is telling a bit of a fib, since even if you deploy script A from Project A, it may be influenced by other configuration, scripts or workflows deployed as part of project B
NetSuite projects are not independent in the same degree as say, traditional software executables. Traditional software has it's own runtime and if far more independent than NS customizations in the general.
but I can appreciate and agree with the desire to make independent things as independent as possible.
it's my acceptance that projects are sometimes intertwined due to the shared single NS environment that all projects deploy to which leads me to my hybrid approach. Indeed my pre-NetSuite best practice would be to always build and deploy ALL The Bits for an application, so you'd be sure of exactly what's in the total build and what's not.
That's neigh impossible with NS, and would be risky since humans can also mess with the target environment - that's typically not a concern for traditional software development. (i.e. developers and/or IT are in complete control of the entire environment in a typical traditional software development scenario)
d
I used to do the same before I decided to switch to SDF. So now I’m going to try that way. Will see how it works. 🙂
s
note that my hybrid approach does rely on the version control system (git in our case) branching [to give separate work efforts their own temporary copy of deploy.xml] and tagging [to capture the state of the entire tree at release] features to make it all work as a tolerable process.
the extreme solutions (1 SDF project for entire NS account or separate project for every little thing) doesn't rely so much on version control system features.
d
By the way, do you use scripts deployment throw project:objects?
s
I'm not sure I understand that question? if there is an SDF 'project:objects' command I'm not familiar with it?
d
Sorry, I meant object:import
s
do I use
object:import
- sure - that's the easiest way to get things into the project AFAIK. In fact, that's one of the commands where I tend to use the webstorm plugin because it provides a more pleasant UI for searching/importing
186 Views