Migrating Existing Web.Link Applications to Creo.JS
This section describes how to migrate existing Web.Link to Creo.JS.
Guidelines to Migrate the Applications
Use the following guidelines to move existing Web.Link applications to Creo.JS.
While Creo.JS supports the same set of APIs as Web.Link, it implements some data representation changes to work with the most recent ECMAScript extensions. The subsequent sections of the guide explain the API changes.
This new approach improves the development productivity. The weblink.legacy.creojs script reduces the effort of migrating the existing Web.Link applications. weblink.legacy.creojs wraps most of the Creo.JS-style APIs into old Web.Link-style APIs. This enables developers to preserve the old style during the migration. See the subsequent sections for information on where Web.Link style is supported by including the weblink.legacy.creojs script.
<script type="text/creojs" src=weblink.legacy.creojs></script>
Use Arrays for Basic Types Collections
In Web.Link an array of integers is created as intseq.
<script>
    var intPath=pfcCreate ("intseq"); // Create sequence
    intPath.Append (1); // Append item
    // . . .
    intPath.Append (4); // Append item
    // Remove last item
    intPath.Remove (intPath.Count - 1, intPath.Count);
</script>          
In Creo.JS an array of integers is created as intPath.
<script type="text/creojs" id=arrayvsseq.creojs>
    const intPath=[]; // Create array
    intPath.push (1); // Push item 1
    intPath.push (2,3,4); // Push a group of items 2,3,4
    // Remove last item
    intPath.pop ();
</script>
In Creo.JS you can also use an array initializer.
<script type="text/creojs" id=arrayvsseq.creojs>
    const intPath=[1,2,3,4]; // Create and initialize array
    // Remove last item
    intPath.pop ();
</script>
If you want to pass a sequence as an argument to a Web.Link method, you can pass an array of JavaScript objects. The conversion of the array to sequence is done internally.
The existing Web.Link style can be retained by including the weblink.legacy.creojs script.
Additional API Features Introduced in Creo.JS
Getting Creo Object Type Information
Creo API object hierarchy design uses multiple inheritance hierarchy to model the API concepts. Use JavaScript instanceof construct to check only the most derived type of the object. To check if object is an instance of any intermediate class in the hierarchy use isInstanceOf() method as shown in the following example. Note that the API accepts either string type name pfcAssembly or type variable pfcModel.getClassName() method to return the name of object class as a string.
<script type="text/creojs" id=typeinfoexample.creojs>
  let currentModel = pfcGetCurrentSession().CurrentModel
  print (currentModel.isInstanceOf (pfcAssembly))
  print (currentModel.isInstanceOf (pfcModel))
  print (currentModel.isInstanceOf (pfcSolid))
  print (currentModel.isInstanceOf (currentModel.getClassName()))
</script>
Managing Session Data
While each set of Creo.JS scripts that belong to the same page work in their isolated contexts, they can interact with each other through session storage maintained in the Creo.JS global context. The following functions manipulate this context:
•  saveToSession(key, value)—Saves value to the global session map under the name key.
•  getFromSession(key)—Returns the global session map value saved under the given name.
•  removeFromSession(key)—Removes value from the global session map specified by the given key.
Managing User Application Data
Creo.JS contains a set of functions that allows you to store and access data in your Application Data (AppData) folder (both local and roaming.) The following functions enable you to manipulate application data:
•  saveToAppData(relativeFileName, data, roaming=false)—Saves the given data string to a file inside your AppData folder for Creo.JS data (CreoJS/data by default). Relative file name may contain directories. If such a directory does not exist in getCreojsAppDataFolder(roaming), it is created.
•  getFromAppData(relativeFileName, roaming=false)—Reads a specified file from your AppData folder for Creo.JS data. The function throws an exception if the file does not exist. On success returns a string with the content of the specified file.
•  deleteFromAppData(relativeFileName, roaming=false)—Removes specified file from your AppData folder. The function throws an exception on failure.
•  existsAppData(relativeFileName, roaming=false)—Returns true when a file with the given relative name exists in getRoamingAppDataFolder(roaming), false otherwise.
The following functions enable you to retrieve the full name of your AppData folders:
•  getAppDataFolder(roaming=false)—Returns the full name of the current user’s AppData folder –Local (default) or Roaming.
•  getLocalAppDataFolder()—Returns the full name of the current user’ s Local subfolder inside the AppData folder. Same as %LOCALAPPDATA% or getAppDataFolder(false).
•  getRoamingAppDataFolder()—Returns the full name of the current user’s Roaming subfolder inside the AppData folder. Same as %APPDATA% or getAppDataFolder(true).
•  getCreojsAppDataFolder(roaming=false)—Returns the full name of the directory inside the current user's AppData designated to store Creo.JS objects. By default, it is CreoJS/data. Can be reconfigured through the setting appdata_subdir in the creo_js_app.conf file.
•  getCreojsLocalAppDataFolder()—Same as getCreojsAppDataFolder(false).
•  getCreojsRoamingAppDataFolder()—Same as getCreojsAppDataFolder(true).
Uploading or Downloading Data to and from the Web server
•  uploadFile(URL, filePath, responseHandler=null)—Uploads the specified file to the specified server. If responseHandler in not provided, works in sync mode and returns a URL received from the server on success. The function throws an exception on failure.
If responseHandler is specified, the function returns an empty string and executes the responseHandler upon completing the upload providing HTTP response object as an argument of the responseHandler.
Note
You must have read access to the directory from which you are trying to upload the file.
For example:
function respHandler (httpResponse) {
				print ('Response received: ' + 
						JSON.stringify (httpResponse, null, 4));
}
uploadFile ('http://my.server.com/upload.php', 'my_file.bin',
					respHandler);
•  uploadFiles(URL, jsonOptions , responseHandler=null)—Uploads one or more files with a single request. Unlike uploadFile method, this function uses multipart mode. For each file to be uploaded you can specify a name by setting the fieldName as jsonOptions and content type.
In sync mode where no response handler provided, the function returns a string representation of a JSON containing information about each uploaded file on success. If response handler is specified, the returned JSON response will be passed as an argument of the response handler.
For example:
let resp = uploadFiles (
					'http://my.server.com/filestorage/upload.cgi',
					{filePath: 'project.gif', fieldName: 'fileToUpload'},
					{filePath: 'config.pro', fieldName: 'anotherFileToUpload'
					       	 	contentType: 'plain/text'}
);
•  downloadFile(URL, filePath, responseHandler=null)—Downloads a file from the server and saves it with the specified name. LikeuploadFile this function also works in sync or async mode. In sync mode it returns the name of the file on success or throws an exception on failure.
Note
You must have write access to the download directory.
•  uploadString(URL, valueToUpload, responseHandler=null)—Uploads a string to the server. It works like uploadFile, however uploads a simple string and not a file.
•  downloadString(URL, responseHandler=null)—Downloads a string from the specified URL. In sync mode, it returns the body of the HTTP response as a string on success or throws an exception on failure.
For example:
let resp = uploadString (
						'http://my.server.com/uploadMessage.php',
						'Message to send to server'
);
print (`Retrieve though: ${resp}`);
let content = downloadString (resp);
print (`downloaded content:\n<div><i>${content}</i></div>`);
•  uploadJSON(URL, jsonObject, responseHandler=null)—Uploads a JSON object to the Web server. Works like uploadString applied to JSON stringified jsonObject, however uses Content-Type: application/json when sending the HTTP request.
•  downloadJSON(URL, responseHandler=null)—Downloads a string from the specified server and then parses it to convert to a JSON object. In sync mode, returns this object, and in async mode, converts the body of the HTTP response to the JSON object and then invokes the responseHandler.
For example:
const respHandler = function (httpResponse) {
				if (httpResponse.statusCode == 200 && httpResponse.body) {
						 print (`Address: ${httpResponse.body.street},
								${httpResponse.body.city},
								${httpResponse.body.state} 
								${httpResponse.body.zip}`);
				}
};
downloadJSON ('http://my.server.com/download.php&myfile',
	respHandler
);		
Reading and Writing files
Creo.JS provides functions to access the local files.
Note
You must have read and write access rights to the folders in which the files are located.
•  readFileAsString(filename)—Reads the content of the specified file and returns it as a single string. The parameter filename is either a full or a relative file name. When the relative file name is provided, the file is searched for in the working directory. The function throws an exception in case of failure.
Note
This function is defined only if the config.pro file contains the option web_link_file_read set as YES.
•  writeFileAsString (filename, text)—Writes specified text to the specified file. The parameter filename is either a full or a relative file name. When the relative file name is provided, the file is searched for in the working directory. The function, throws an exception in case of failure.
Note
This function is defined only if the config.pro file contains the option web_link_file_read set as YES.
Creo.JS Web server
Creo.JS has an internal Web server that provides access to Creo.JS from remote computers and allows you to access Creo.JS via HTTP protocols and through web sockets. It also lets you use Chrome DevTools for remote debugging of the Creo.JS script. The following functions manage the Web server:
•  startWebServer(port=-1)—Starts the Web server listening on the given port. When port is set to -1, the value of the port is taken from the configuration file creo_js_app.conf. When port is set to 0, server will start on any available port, otherwise the server will try to start on the specified port.
•  isWebServerStarted()—Returns true if the Web server is successfully started, false otherwise.
•  getWebServerPort()—Returns the port number on which the Web server is listening. If the Web server is not started, the function returns -1.
•  addWebSocketServerHandler(path, dataHandler, closeHandler=null, errorHandler=null, openHandler=null) or addWebSocketServerHandler(path, {dataHandler, closeHandler, errorHandler, openHandler})Sets a web socket handler for the specified path. The second parameter is an object that may contain the following handlers:
  dataHandlerfunction (WebSocketConnection conn, string msg)
  closeHandlerfunction (WebSocketConnection conn)
  errorHandlerfunction (WebSocketConnection conn, string msg)
  openHandlerfunction (WebSocketConnection conn)
For example:
addWebSocketServerHandler ('/test', {
				dataHandler: function (conn, msg) {
							print (`'/test' handler received message:
											<div>${msg}</div>`);
							conn.send (`'/test' handler successfully received 
									${msg.length} bytes`);
  				 }
		 errorHandler: function (conn, err) {
				        print (`Error: ${err}`);}
				}
);
•  removeWebSocketServerHandler(path)—Removes a web socket handler that corresponds to the specified path.
•  addServerHandler(path, dataHandler, method=RequestMethod.ALL)—Sets a Web server handler for the specified path. Data handler is the function function (WebServerRequest req, WebServerResponse resp) that processes the requests.
Request req contains information about the incoming request, while response resp has tools for sending response. The method argument specifies the type or types of requests this handler serves. Following are the possible values:
  RequestMethod.GET,
  RequestMethod.POST,
  RequestMethod.PUT,
  RequestMethod.HEAD,
  RequestMethod.PUT,
  RequestMethod.DELETE,
  RequestMethod.OPTIONS,
  RequestMethod.PATCH,
  RequestMethod.ALL
  or any combinations of the above.
For example:
addServerHandler ('/api', 
		   	 function (req, resp) {
				    	 print (`Executing function ${req.GET['function']}`);
                	var res = execute (req.GET['function'], 
											    req.GET ['arg']);
						resp.writeHead (200, 'OK', 
								{'Content-type': 'application/json'})
								.end (JSON.stringify (res));
		}, RequestMethod.GET);
•  object WebServerRequestCreo.JS type that contains the following methods:
  url(string)
  headers(map)
  method(string)
  query(string)—part of the URL address after '?' (not including)
  remoteAddress(string)—address of the machine that sent the request
  remotePort(int)—port of the remote machine
  contentType(string)—value of the 'Content-Type' header
  body(string)—body of the request
  GET(map)—all arguments from the query string
  POST(map)—all arguments from the body of the POST request
  PARAMS(map)—all arguments from the combined methods
  saveToFile(filename)—saves the body of the request in the given file, provided Creo.JS has write access to the directory. If filename is a relative path, it is considered from the Creo current running directory.
  saveToAppDataFile(relFileName, roaming=false)—saves the body of the request to a file located in the current user’s AppData folder Local or Roaming.
•  object WebServerResponseCreo.JS type that has the following methods:
  writeHead(statusCode, statusMessage, headers {name:value})
  setHeader(name, value) — add response header
  write(data)—append the data to the response body
  writeFromFile write(filename)—writes the specified file to the response output stream, provided Creo.JS has read access to the directory, where the file is located.
  writeFromAppDataFile(relFileName, roaming=false)—writes contents of the specified file from the current user’s AppData Local or Roaming folder to the response stream
  end (data=null)—complete and send the response
•  removeServerHandler(path)—Removes the Web server handler for the given path.
•  stopWebServer()—Stops the currently running Web server.
Including External Scripts
You can split complex scripts into a set of scripts where one main script uses other scripts as libraries in Creo.JS. This is implemented through the require method like NodeJS has.
•  require(requiredScriptName)—Behaves in the same way NodeJS require does: embraces the code in the required file with function (module, exports){and },) executes the created function and returnsmodule.exports as the result. Searches for the requiredScriptName in the current script directory, then in the directory one level up, and so on until the file in need is found or directory under consideration is not an accessible directory, then keeps searching in the getScriptPath().
When a file was successfully required (found and executed) in a context, it gets cached for this context and all consecutive calls of the require function with this script returns the cached value.
•  forgetRequired(requiredScriptName)—Removes the required file from cache. That is, consecutive calls of require results in reloading and re-executing the required script. This function could be helpful in the developing stage.
•  forgetAllRequired()—Removes all cached required scripts from the current context.
Accessing Scripts Local Location
Creo.JS has an API that gives you access to locally stored script files:
•  getScriptPath()—Returns an array of folders where require is looking for a required script. The script path is to be set in the creo_js_app.conf file by setting js_path property.
•  getScriptFolder()—Returns the full path of the directory JavaScript scripts located in.
•  getScriptsList()—Returns a string containing a list of all scripts names from getScriptFolder() separated by commas. Script names are the relative names to getScriptFolder().
•  getScripts()—Returns an array of all script names from getScriptFolder().
Other API Features
•  setCIPSequenceHandler(arrayHandler)—Sets a JavaScript callback that gets executed every time an invoked OTK method returns a CIP sequence. All CIP sequences get converted to JavaScript arrays. This callback allows you to define a function which takes a CIP sequence converted to an array and define some methods. For example, Item(), Set(), Append(), etc. to make it behave similar to WebLink sequences for backward compatibility. See how weblink.legacy.creojs uses this function.
•  setUseCIPSequenceHandler(bool on)—Turns on/off the invocation of the CIP sequence handler (if set.)
setUseCIPSequenceHandler(false) works like setCIPSequenceHandler(null). If CIP sequence handler is not set, this function has no effect.
•  setOnContextClose(handler)—Sets a JavaScript callback to execute upon closing the current context. For example, when the embedded browser window which is open for the current context, is closed.
•  help (name=’’) —Opens a browser window with OTK help for the specified class or class method. The argument name can be either a className or className.MethodName. For example:
help ('pfcSession');
help ('pfcSession.GetAppInfo');
•  print(message)—Prints a given message to the current browser window.
Array-Like Structures
Creo.JS has array-like structures.
•  Additional features are introduced on array-like structures, which represent two and three dimensional concepts, such as, pfcPoint3D, pfcPoint2D, pfcMatrix3D, and so on.
•  Properties x, y, z, if applicable, representing get(0), get (1), and get(2) respectively.
•  Method dims()—Returns an array of sizes for each dimension.
•  Method dim(dimensionIndex)—Returns the size of the dimension with specified index.